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
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require "cf/cli/app/env"
|
|
3
|
+
|
|
4
|
+
module CF
|
|
5
|
+
module App
|
|
6
|
+
describe Env do
|
|
7
|
+
before do
|
|
8
|
+
stub_client
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe '#set_env' do
|
|
12
|
+
let(:mock_restart_command) { MockRestartCommand.new }
|
|
13
|
+
let(:mock_start_command) { MockStartCommand.new }
|
|
14
|
+
let(:client) { build(:client) }
|
|
15
|
+
let(:app) { build(:app, client: client, name: 'puppies-r-us-website') }
|
|
16
|
+
let(:env) { Env.new(Mothership.commands[:set_env]) }
|
|
17
|
+
|
|
18
|
+
before do
|
|
19
|
+
client.stub(:app_by_name).and_return(app)
|
|
20
|
+
env.input = Mothership::Inputs.new(Mothership.commands[:set_env], env, inputs, {}, {})
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
context 'when name and value are specified' do
|
|
24
|
+
let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING', value: 'oh_what_a_value'} }
|
|
25
|
+
|
|
26
|
+
it 'updates the app with the new environment variable' do
|
|
27
|
+
expect(app.env['MY_LOVELY_SETTING']).to eq(nil)
|
|
28
|
+
expect(app).to receive(:update!) do
|
|
29
|
+
expect(app.env['MY_LOVELY_SETTING']).to eq('oh_what_a_value')
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
capture_output { env.set_env }
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
context "when the environment variable is specified with the 'VAR=VALUE' format" do
|
|
37
|
+
let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING=oh_what_a_value'} }
|
|
38
|
+
|
|
39
|
+
it 'updates the app with the new environment variable' do
|
|
40
|
+
expect(app.env['MY_LOVELY_SETTING']).to eq(nil)
|
|
41
|
+
expect(app).to receive(:update!) do
|
|
42
|
+
expect(app.env['MY_LOVELY_SETTING']).to eq('oh_what_a_value')
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
capture_output { env.set_env }
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe "environment variable format" do
|
|
50
|
+
context "when the name has only letters, numbers, and underscores" do
|
|
51
|
+
let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING123', value: "oh_what_a_value"} }
|
|
52
|
+
it "gets the value from the input[:value]" do
|
|
53
|
+
expect(app.env['MY_LOVELY_SETTING123']).to eq(nil)
|
|
54
|
+
app.stub(:update!)
|
|
55
|
+
|
|
56
|
+
capture_output { env.set_env }
|
|
57
|
+
expect(app.env['MY_LOVELY_SETTING123']).to eq("oh_what_a_value")
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
context "when the name has one equal sign, and is otherwise valid" do
|
|
62
|
+
let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING123=oh_what_a_value'} }
|
|
63
|
+
it "gets the value by parsing the name" do
|
|
64
|
+
expect(app.env['MY_LOVELY_SETTING123']).to eq(nil)
|
|
65
|
+
app.stub(:update!)
|
|
66
|
+
|
|
67
|
+
capture_output { env.set_env }
|
|
68
|
+
expect(app.env['MY_LOVELY_SETTING123']).to eq("oh_what_a_value")
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
context "but provides a value anyway" do
|
|
72
|
+
let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING123=oh_what_a_value', value: 'my_other_value'} }
|
|
73
|
+
|
|
74
|
+
it "gives the user an error" do
|
|
75
|
+
capture_exceptional_output { env.set_env }
|
|
76
|
+
expect(error_output).to say "You attempted to specify the value of MY_LOVELY_SETTING123 twice."
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
context "when the name has more than one equal sign" do
|
|
82
|
+
let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING123=oh_what_a_value=badbadbad'} }
|
|
83
|
+
it "gives the user an error" do
|
|
84
|
+
capture_exceptional_output { env.set_env }
|
|
85
|
+
expect(error_output).to say "Invalid format: environment variable definition contains too many occurences of '='"
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
context "when there are characters that are not letters, numbers, or underscores" do
|
|
90
|
+
let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING1?#$=value'} }
|
|
91
|
+
it "raises an error" do
|
|
92
|
+
capture_exceptional_output { env.set_env }
|
|
93
|
+
expect(error_output).to say "Invalid format: environment variable names can only contain alphanumeric characters and underscores"
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
context "when the name starts with a number" do
|
|
98
|
+
let(:inputs) { {app: app, name: '1MY_LOVELY_SETTING', value: 'oh_what_a_value'} }
|
|
99
|
+
it "raises an error" do
|
|
100
|
+
capture_exceptional_output { env.set_env }
|
|
101
|
+
expect(error_output).to say "Invalid format: environment variable names cannot start with a number"
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
context 'when the app is not started' do
|
|
107
|
+
context 'with the --restart flag' do
|
|
108
|
+
let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING', value: 'oh_what_a_value', restart: true} }
|
|
109
|
+
before { Start.stub(:new).and_return(mock_start_command) }
|
|
110
|
+
|
|
111
|
+
it 'starts the app' do
|
|
112
|
+
expect(app).to receive(:update!) do
|
|
113
|
+
expect(mock_start_command.started_apps).to be_empty
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
capture_output { env.set_env }
|
|
117
|
+
expect(output).to say "Your app was unstarted. Starting now."
|
|
118
|
+
|
|
119
|
+
expect(mock_start_command.started_apps).to eq [app]
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
context 'without the --restart flag' do
|
|
124
|
+
let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING', value: 'oh_what_a_value', restart: false} }
|
|
125
|
+
|
|
126
|
+
before do
|
|
127
|
+
app.stub(:update!)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it "suggests a 'truck push' to the user" do
|
|
131
|
+
capture_output { env.set_env }
|
|
132
|
+
expect(output).to say "TIP: Use 'truck push' to ensure your env variable changes take effect."
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
context 'when the app is already started' do
|
|
138
|
+
before do
|
|
139
|
+
app.stub(:started?) { true }
|
|
140
|
+
Restart.stub(:new).and_return(mock_restart_command)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
context 'with the --restart flag' do
|
|
144
|
+
let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING', value: 'oh_what_a_value', restart: true} }
|
|
145
|
+
|
|
146
|
+
it 'restarts the app' do
|
|
147
|
+
expect(app).to receive(:update!) do
|
|
148
|
+
expect(mock_restart_command.restarted_apps).to be_empty
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
capture_output { env.set_env }
|
|
152
|
+
|
|
153
|
+
expect(mock_restart_command.restarted_apps).to eq([app])
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
context 'without the --restart flag' do
|
|
158
|
+
let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING', value: 'oh_what_a_value', restart: false} }
|
|
159
|
+
before do
|
|
160
|
+
app.stub(:update!)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
it 'does not restart the app but suggests a cf push' do
|
|
164
|
+
capture_output { env.set_env }
|
|
165
|
+
expect(mock_restart_command.restarted_apps).to be_empty
|
|
166
|
+
expect(output).to say "TIP: Use 'truck push' to ensure your env variable changes take effect."
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
describe '#unset_env' do
|
|
173
|
+
let(:app) { build(:app, client: client, name: 'puppies-r-us-website', environment_json: {'MY_LOVELY_SETTING' => 'oh_so_lovely'}) }
|
|
174
|
+
let(:client) { build(:client) }
|
|
175
|
+
let(:env) { Env.new(Mothership.commands[:unset_env]) }
|
|
176
|
+
let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING'} }
|
|
177
|
+
let(:mock_start_command) { MockStartCommand.new }
|
|
178
|
+
let(:mock_restart_command) { MockRestartCommand.new }
|
|
179
|
+
|
|
180
|
+
before do
|
|
181
|
+
env.input = Mothership::Inputs.new(Mothership.commands[:unset_env], env, inputs, {}, {})
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
it 'unsets the environment variable and updates the app' do
|
|
185
|
+
expect(app.env['MY_LOVELY_SETTING']).to eq('oh_so_lovely')
|
|
186
|
+
expect(app).to receive(:update!) do
|
|
187
|
+
expect(app.env['MY_LOVELY_SETTING']).to be_nil
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
capture_output { env.unset_env }
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
context 'when the app is not started' do
|
|
194
|
+
context 'with the --restart flag' do
|
|
195
|
+
let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING', restart: true} }
|
|
196
|
+
before { Start.stub(:new).and_return(mock_start_command) }
|
|
197
|
+
|
|
198
|
+
it 'starts the app' do
|
|
199
|
+
expect(app).to receive(:update!) do
|
|
200
|
+
expect(mock_start_command.started_apps).to be_empty
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
capture_output { env.unset_env }
|
|
204
|
+
expect(output).to say "Your app was unstarted. Starting now."
|
|
205
|
+
|
|
206
|
+
expect(mock_start_command.started_apps).to eq [app]
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
context 'without the --restart flag' do
|
|
211
|
+
let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING'} }
|
|
212
|
+
|
|
213
|
+
before do
|
|
214
|
+
app.stub(:update!)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
it "suggests a 'truck push' to the user" do
|
|
218
|
+
capture_output { env.unset_env }
|
|
219
|
+
expect(output).to say "TIP: Use 'truck push' to ensure your env variable changes take effect."
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
context 'when the app is already started' do
|
|
225
|
+
before do
|
|
226
|
+
app.stub(:started?) { true }
|
|
227
|
+
Restart.stub(:new).and_return(mock_restart_command)
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
context 'with the --restart flag' do
|
|
231
|
+
let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING', restart: true} }
|
|
232
|
+
|
|
233
|
+
it 'restarts the app' do
|
|
234
|
+
expect(app).to receive(:update!) do
|
|
235
|
+
expect(mock_restart_command.restarted_apps).to be_empty
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
capture_output { env.unset_env }
|
|
239
|
+
|
|
240
|
+
expect(mock_restart_command.restarted_apps).to eq([app])
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
context 'without the --restart flag' do
|
|
245
|
+
let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING', restart: false} }
|
|
246
|
+
before do
|
|
247
|
+
app.stub(:update!)
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
it 'does not restart the app but suggests a cf push' do
|
|
251
|
+
capture_output { env.unset_env }
|
|
252
|
+
expect(mock_restart_command.restarted_apps).to be_empty
|
|
253
|
+
expect(output).to say "TIP: Use 'truck push' to ensure your env variable changes take effect."
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
module CF
|
|
4
|
+
module App
|
|
5
|
+
describe Events do
|
|
6
|
+
let(:global) { {} }
|
|
7
|
+
let(:given) { {} }
|
|
8
|
+
let(:inputs) { {:app => apps[0]} }
|
|
9
|
+
let(:apps) { [build(:app)] }
|
|
10
|
+
|
|
11
|
+
before do
|
|
12
|
+
inputs[:app].stub(:events) do
|
|
13
|
+
[double("AppEvent", {
|
|
14
|
+
:instance_guid => "some_guid",
|
|
15
|
+
:instance_index => 1,
|
|
16
|
+
:exit_status => -1,
|
|
17
|
+
:exit_description => "Something very interesting",
|
|
18
|
+
:timestamp => "2013-05-15 18:52:17 +0000" }),
|
|
19
|
+
double("AppEvent", {
|
|
20
|
+
:instance_guid => "some_other_guid",
|
|
21
|
+
:instance_index => 0,
|
|
22
|
+
:exit_status => 0,
|
|
23
|
+
:exit_description => "Something less interesting",
|
|
24
|
+
:timestamp => "2013-05-15 18:52:15 +0000" })]
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
subject do
|
|
29
|
+
capture_output { Mothership.new.invoke(:events, inputs, given, global) }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe "metadata" do
|
|
33
|
+
let(:command) { Mothership.commands[:events] }
|
|
34
|
+
|
|
35
|
+
describe "command" do
|
|
36
|
+
subject { command }
|
|
37
|
+
its(:description) { should eq "Display application events" }
|
|
38
|
+
it { expect(Mothership::Help.group(:apps, :info)).to include(subject) }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
include_examples "inputs must have descriptions"
|
|
42
|
+
|
|
43
|
+
describe "arguments" do
|
|
44
|
+
subject { command.arguments }
|
|
45
|
+
it "has arguments that are not needed with a manifest" do
|
|
46
|
+
should eq([:name => :app, :type => :optional, :value => nil])
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "prints out progress" do
|
|
52
|
+
subject
|
|
53
|
+
stdout.rewind
|
|
54
|
+
expect(stdout.readlines.first).to match /Getting events for #{apps.first.name}/
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "prints out headers" do
|
|
58
|
+
subject
|
|
59
|
+
stdout.rewind
|
|
60
|
+
expect(stdout.readlines[2]).to match /time\s+instance\s+index\s+description\s+exit\s+status/
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "prints out the events in order" do
|
|
64
|
+
subject
|
|
65
|
+
stdout.rewind
|
|
66
|
+
expect(stdout.readlines[3]).to match /.*2013-05-15 18:52:15 \+0000\s+0\s+Something less interesting\s+Success \(0\).*/
|
|
67
|
+
stdout.rewind
|
|
68
|
+
expect(stdout.readlines[4]).to match /.*2013-05-15 18:52:17 \+0000\s+1\s+Something very interesting\s+Failure \(-1\).*/
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
module CF
|
|
4
|
+
module App
|
|
5
|
+
describe "Help" do
|
|
6
|
+
let(:global) { {} }
|
|
7
|
+
let(:given) { {} }
|
|
8
|
+
|
|
9
|
+
subject do
|
|
10
|
+
capture_output { Mothership.new.invoke(:help, :command => "app") }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "describes the command" do
|
|
14
|
+
subject
|
|
15
|
+
stdout.rewind
|
|
16
|
+
expect(stdout.readlines.first).to match /Show app information/
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "prints the options" do
|
|
20
|
+
subject
|
|
21
|
+
stdout.rewind
|
|
22
|
+
expect(stdout.readlines.any? {|line| line =~ /Options:/ }).to be_true
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context "when the user is not logged in" do
|
|
27
|
+
before do
|
|
28
|
+
capture_output { Mothership.new.invoke(:logout) }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "does not require login" do
|
|
32
|
+
subject
|
|
33
|
+
stdout.rewind
|
|
34
|
+
expect(stdout.readlines.first).to_not match /Please log in first to proceed/
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require "stringio"
|
|
3
|
+
|
|
4
|
+
module CF
|
|
5
|
+
module App
|
|
6
|
+
describe Stats do
|
|
7
|
+
let(:global) { {:color => false} }
|
|
8
|
+
let(:inputs) { {:app => apps[0]} }
|
|
9
|
+
let(:given) { {} }
|
|
10
|
+
let(:client) { build(:client) }
|
|
11
|
+
let(:apps) { [build(:app, :client => client, :name => "basic-app-name")] }
|
|
12
|
+
let(:time) { Time.local(2012, 11, 1, 2, 30) }
|
|
13
|
+
|
|
14
|
+
before do
|
|
15
|
+
client.stub(:apps).and_return(apps)
|
|
16
|
+
CF::CLI.any_instance.stub(:client).and_return(client)
|
|
17
|
+
CF::CLI.any_instance.stub(:precondition).and_return(nil)
|
|
18
|
+
|
|
19
|
+
client.base.stub(:instances).with(anything) do
|
|
20
|
+
{
|
|
21
|
+
"12" => {:state => "STOPPED", :since => time.to_i, :debug_ip => "foo", :debug_port => "bar", :console_ip => "baz", :console_port => "qux"},
|
|
22
|
+
"1" => {:state => "STOPPED", :since => time.to_i, :debug_ip => "foo", :debug_port => "bar", :console_ip => "baz", :console_port => "qux"},
|
|
23
|
+
"2" => {:state => "STARTED", :since => time.to_i, :debug_ip => "foo", :debug_port => "bar", :console_ip => "baz", :console_port => "qux"}
|
|
24
|
+
}
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
subject do
|
|
29
|
+
capture_output do
|
|
30
|
+
Mothership.new.invoke(:instances, inputs, given, global)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe "metadata" do
|
|
35
|
+
let(:command) { Mothership.commands[:instances] }
|
|
36
|
+
|
|
37
|
+
describe "command" do
|
|
38
|
+
subject { command }
|
|
39
|
+
its(:description) { should eq "List an app's instances" }
|
|
40
|
+
it { expect(Mothership::Help.group(:apps, :info)).to include(subject) }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
include_examples "inputs must have descriptions"
|
|
44
|
+
|
|
45
|
+
describe "arguments" do
|
|
46
|
+
subject { command.arguments }
|
|
47
|
+
it "has no arguments" do
|
|
48
|
+
should eq([{:type => :splat, :value => nil, :name => :apps}])
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "prints out the instances in the correct order" do
|
|
54
|
+
subject
|
|
55
|
+
expect(output).to say("instance #1")
|
|
56
|
+
expect(output).to say("instance #2")
|
|
57
|
+
expect(output).to say("instance #12")
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "prints out one of the instances correctly" do
|
|
61
|
+
subject
|
|
62
|
+
expect(output).to say("instance #2: started")
|
|
63
|
+
expect(output).to say(" started: #{time.strftime("%F %r")}")
|
|
64
|
+
expect(output).to say(" debugger: port bar at foo")
|
|
65
|
+
expect(output).to say(" console: port qux at baz")
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
module CF
|
|
4
|
+
module App
|
|
5
|
+
describe Create do
|
|
6
|
+
let(:inputs) { {} }
|
|
7
|
+
let(:given) { {} }
|
|
8
|
+
let(:global) { {:color => false, :quiet => true} }
|
|
9
|
+
|
|
10
|
+
let(:service_instances) { Array.new(5) { build(:managed_service_instance) } }
|
|
11
|
+
let(:lucid64) { build(:stack, :name => "lucid64") }
|
|
12
|
+
let(:client) { build(:client) }
|
|
13
|
+
|
|
14
|
+
before do
|
|
15
|
+
CF::CLI.any_instance.stub(:client).and_return(client)
|
|
16
|
+
client.stub(:service_instances).and_return(service_instances)
|
|
17
|
+
client.stub(:stacks).and_return([lucid64])
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
let(:path) { "some-path" }
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def setup_create
|
|
24
|
+
command = Mothership.commands[:push]
|
|
25
|
+
push_command = CF::App::Push.new(command)
|
|
26
|
+
push_command.path = path
|
|
27
|
+
push_command.input = Mothership::Inputs.new(command, push_command, inputs, given, global)
|
|
28
|
+
push_command.extend CF::App::PushInteractions
|
|
29
|
+
push_command
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
let(:push_command) { setup_create }
|
|
33
|
+
|
|
34
|
+
describe "#get_inputs" do
|
|
35
|
+
subject { push_command.get_inputs }
|
|
36
|
+
|
|
37
|
+
let(:given) do
|
|
38
|
+
{:name => "some-name",
|
|
39
|
+
:instances => "1",
|
|
40
|
+
:plan => "100",
|
|
41
|
+
:memory => "1G",
|
|
42
|
+
:command => "ruby main.rb",
|
|
43
|
+
:buildpack => "git://example.com",
|
|
44
|
+
:stack => "lucid64"
|
|
45
|
+
}
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
context "when all the inputs are given" do
|
|
49
|
+
its([:name]) { should eq "some-name" }
|
|
50
|
+
its([:total_instances]) { should eq 1 }
|
|
51
|
+
its([:space]) { should eq client.current_space }
|
|
52
|
+
its([:command]) { should eq "ruby main.rb" }
|
|
53
|
+
its([:memory]) { should eq 1024 }
|
|
54
|
+
its([:stack]) { should eq lucid64 }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
context "when the command is given" do
|
|
58
|
+
context "and there is a Procfile in the application's root" do
|
|
59
|
+
before do
|
|
60
|
+
FakeFS.activate!
|
|
61
|
+
Dir.mkdir(path)
|
|
62
|
+
|
|
63
|
+
File.open("#{path}/Procfile", "w") do |file|
|
|
64
|
+
file.write("this is a procfile")
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
after do
|
|
69
|
+
FakeFS.deactivate!
|
|
70
|
+
FakeFS::FileSystem.clear
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
its([:command]) { should eq "ruby main.rb" }
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
context "when certain inputs are not given" do
|
|
78
|
+
it "asks for the name" do
|
|
79
|
+
given.delete(:name)
|
|
80
|
+
should_ask("Name") { "some-name" }
|
|
81
|
+
subject
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "asks for the total instances" do
|
|
85
|
+
given.delete(:instances)
|
|
86
|
+
should_ask("Instances", anything) { 1 }
|
|
87
|
+
subject
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
context "when the command is not given" do
|
|
91
|
+
before { given.delete(:command) }
|
|
92
|
+
|
|
93
|
+
it "defaults to nil" do
|
|
94
|
+
expect(subject[:command]).to be_nil
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
describe "getting the start command" do
|
|
98
|
+
before do
|
|
99
|
+
FakeFS.activate!
|
|
100
|
+
Dir.mkdir(path)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
after do
|
|
104
|
+
FakeFS.deactivate!
|
|
105
|
+
FakeFS::FileSystem.clear
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
context "when there is a Procfile in the app's root" do
|
|
109
|
+
before do
|
|
110
|
+
File.open("#{path}/Procfile", "w") do |file|
|
|
111
|
+
file.write("this is a procfile")
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it "does not ask for a start command" do
|
|
116
|
+
dont_allow_ask("Startup command")
|
|
117
|
+
subject
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
context "when there is no Procfile in the app's root" do
|
|
122
|
+
it "is nil" do
|
|
123
|
+
expect(subject[:command]).to be_nil
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it "asks for the memory" do
|
|
130
|
+
given.delete(:memory)
|
|
131
|
+
|
|
132
|
+
memory_choices = %w(64M 128M 256M 512M 1G)
|
|
133
|
+
push_command.stub(:memory_choices).and_return(memory_choices)
|
|
134
|
+
|
|
135
|
+
should_ask("Memory Limit", anything) do |_, options|
|
|
136
|
+
expect(options[:choices]).to eq memory_choices
|
|
137
|
+
expect(options[:default]).to eq "256M"
|
|
138
|
+
"1G"
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
subject
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
describe "#create_app" do
|
|
147
|
+
before { dont_allow_ask }
|
|
148
|
+
|
|
149
|
+
let(:app) { double(:app, :name => "some-app").as_null_object }
|
|
150
|
+
let(:space) { double(:space, :name => "some-space") }
|
|
151
|
+
|
|
152
|
+
let(:attributes) do
|
|
153
|
+
{:name => "some-app",
|
|
154
|
+
:total_instances => 2,
|
|
155
|
+
:memory => 1024,
|
|
156
|
+
:buildpack => "git://example.com"
|
|
157
|
+
}
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
before do
|
|
161
|
+
client.stub(:app).and_return(app)
|
|
162
|
+
client.stub(:current_space).and_return(space)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
subject { push_command.create_app(attributes) }
|
|
166
|
+
|
|
167
|
+
context "when the user does not have permission to create apps" do
|
|
168
|
+
it "fails with a friendly message" do
|
|
169
|
+
app.stub(:create!).and_raise(CFoundry::NotAuthorized, "foo")
|
|
170
|
+
|
|
171
|
+
expect { subject }.to raise_error(
|
|
172
|
+
CF::UserError,
|
|
173
|
+
"You need the Project Developer role in some-space to push.")
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
context "with an invalid buildpack" do
|
|
178
|
+
before do
|
|
179
|
+
app.stub(:create!) do
|
|
180
|
+
raise CFoundry::MessageParseError.new(
|
|
181
|
+
"Request invalid due to parse error: Field: buildpack, Error: Value git@github.com:cloudfoundry/heroku-buildpack-ruby.git doesn't match regexp String /GIT_URL_REGEX/",
|
|
182
|
+
1001)
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it "fails and prints a pretty message" do
|
|
187
|
+
push_command.stub(:line).with(anything)
|
|
188
|
+
expect { subject }.to raise_error(
|
|
189
|
+
CF::UserError, "Buildpack must be a public git repository URI.")
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
describe "#map_url" do
|
|
195
|
+
let(:app) { double(:app, :space => space, name: "app-name").as_null_object }
|
|
196
|
+
let(:space) { double(:space, :domains => domains) }
|
|
197
|
+
let(:domains) { [double(:domain, :name => "foo.com")] }
|
|
198
|
+
let(:hosts) { [app.name] }
|
|
199
|
+
|
|
200
|
+
subject { push_command.map_route(app) }
|
|
201
|
+
|
|
202
|
+
it "asks for a subdomain with 'none' as an option" do
|
|
203
|
+
should_ask("Subdomain", anything) do |_, options|
|
|
204
|
+
expect(options[:choices]).to eq(hosts + %w(none))
|
|
205
|
+
expect(options[:default]).to eq hosts.first
|
|
206
|
+
hosts.first
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
stub_ask("Domain", anything) { domains.first }
|
|
210
|
+
|
|
211
|
+
push_command.stub(:invoke)
|
|
212
|
+
|
|
213
|
+
subject
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
it "asks for a domain with 'none' as an option" do
|
|
217
|
+
stub_ask("Subdomain", anything) { hosts.first }
|
|
218
|
+
|
|
219
|
+
should_ask("Domain", anything) do |_, options|
|
|
220
|
+
expect(options[:choices]).to eq(domains + %w(none))
|
|
221
|
+
expect(options[:default]).to eq domains.first
|
|
222
|
+
domains.first
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
push_command.stub(:invoke)
|
|
226
|
+
|
|
227
|
+
subject
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
it "maps the host and domain after both are given" do
|
|
231
|
+
stub_ask("Subdomain", anything) { hosts.first }
|
|
232
|
+
stub_ask("Domain", anything) { domains.first }
|
|
233
|
+
|
|
234
|
+
push_command.should_receive(:invoke).with(:map,
|
|
235
|
+
:app => app, :host => hosts.first,
|
|
236
|
+
:domain => domains.first)
|
|
237
|
+
|
|
238
|
+
subject
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
context "when 'none' is given as the host" do
|
|
242
|
+
context "and a domain is provided afterwards" do
|
|
243
|
+
it "invokes 'map' with an empty host" do
|
|
244
|
+
should_ask("Subdomain", anything) { "none" }
|
|
245
|
+
stub_ask("Domain", anything) { domains.first }
|
|
246
|
+
|
|
247
|
+
push_command.should_receive(:invoke).with(:map,
|
|
248
|
+
:host => "", :domain => domains.first, :app => app)
|
|
249
|
+
|
|
250
|
+
subject
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
context "when 'none' is given as the domain" do
|
|
256
|
+
it "does not perform any mapping" do
|
|
257
|
+
stub_ask("Subdomain", anything) { "foo" }
|
|
258
|
+
should_ask("Domain", anything) { "none" }
|
|
259
|
+
|
|
260
|
+
push_command.should_not_receive(:invoke).with(:map, anything)
|
|
261
|
+
|
|
262
|
+
subject
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
context "when mapping fails" do
|
|
267
|
+
before do
|
|
268
|
+
should_ask("Subdomain", anything) { "foo" }
|
|
269
|
+
should_ask("Domain", anything) { domains.first }
|
|
270
|
+
|
|
271
|
+
push_command.should_receive(:invoke).with(:map,
|
|
272
|
+
:host => "foo", :domain => domains.first, :app => app) do
|
|
273
|
+
raise CFoundry::RouteHostTaken.new("foo", 1234)
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
it "asks again" do
|
|
278
|
+
push_command.stub(:line)
|
|
279
|
+
|
|
280
|
+
should_ask("Subdomain", anything) { hosts.first }
|
|
281
|
+
should_ask("Domain", anything) { domains.first }
|
|
282
|
+
|
|
283
|
+
push_command.stub(:invoke)
|
|
284
|
+
|
|
285
|
+
subject
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
it "reports the failure message" do
|
|
289
|
+
push_command.should_receive(:line).with("foo")
|
|
290
|
+
push_command.should_receive(:line)
|
|
291
|
+
|
|
292
|
+
stub_ask("Subdomain", anything) { hosts.first }
|
|
293
|
+
stub_ask("Domain", anything) { domains.first }
|
|
294
|
+
|
|
295
|
+
push_command.stub(:invoke)
|
|
296
|
+
|
|
297
|
+
subject
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
describe "#create_services" do
|
|
303
|
+
let(:app) { build(:app, :client => client) }
|
|
304
|
+
subject { push_command.create_services(app) }
|
|
305
|
+
|
|
306
|
+
context "when forcing" do
|
|
307
|
+
let(:inputs) { {:force => true} }
|
|
308
|
+
|
|
309
|
+
it "does not ask to create any services" do
|
|
310
|
+
dont_allow_ask("Create services for application?", anything)
|
|
311
|
+
subject
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
it "does not create any services" do
|
|
315
|
+
push_command.should_not_receive(:invoke).with(:create_service, anything)
|
|
316
|
+
subject
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
context "when not forcing" do
|
|
321
|
+
let(:inputs) { {:force => false} }
|
|
322
|
+
|
|
323
|
+
it "does not create the service if asked not to" do
|
|
324
|
+
should_ask("Create services for application?", anything) { false }
|
|
325
|
+
push_command.should_not_receive(:invoke).with(:create_service, anything)
|
|
326
|
+
|
|
327
|
+
subject
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
it "asks again to create a service" do
|
|
331
|
+
should_ask("Create services for application?", anything) { true }
|
|
332
|
+
push_command.should_receive(:invoke).with(:create_service, {:app => app}, :plan => :interact).ordered
|
|
333
|
+
|
|
334
|
+
should_ask("Create another service?", :default => false) { true }
|
|
335
|
+
push_command.should_receive(:invoke).with(:create_service, {:app => app}, :plan => :interact).ordered
|
|
336
|
+
|
|
337
|
+
should_ask("Create another service?", :default => false) { true }
|
|
338
|
+
push_command.should_receive(:invoke).with(:create_service, {:app => app}, :plan => :interact).ordered
|
|
339
|
+
|
|
340
|
+
should_ask("Create another service?", :default => false) { false }
|
|
341
|
+
push_command.should_not_receive(:invoke).with(:create_service, anything).ordered
|
|
342
|
+
|
|
343
|
+
subject
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
describe "#bind_services" do
|
|
349
|
+
let(:app) { double(:app).as_null_object }
|
|
350
|
+
|
|
351
|
+
subject { push_command.bind_services(app) }
|
|
352
|
+
|
|
353
|
+
context "when forcing" do
|
|
354
|
+
let(:global) { {:force => true, :color => false, :quiet => true} }
|
|
355
|
+
|
|
356
|
+
it "does not ask to bind any services" do
|
|
357
|
+
dont_allow_ask("Bind other services to application?", anything)
|
|
358
|
+
subject
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
it "does not bind any services" do
|
|
362
|
+
push_command.should_not_receive(:invoke).with(:bind_service, anything)
|
|
363
|
+
subject
|
|
364
|
+
end
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
context "when not forcing" do
|
|
368
|
+
it "does not bind the service if asked not to" do
|
|
369
|
+
should_ask("Bind other services to application?", anything) { false }
|
|
370
|
+
push_command.should_not_receive(:invoke).with(:bind_service, anything)
|
|
371
|
+
|
|
372
|
+
subject
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
it "asks again to bind a service" do
|
|
376
|
+
bind_times = 3
|
|
377
|
+
call_count = 0
|
|
378
|
+
|
|
379
|
+
should_ask("Bind other services to application?", anything) { true }
|
|
380
|
+
|
|
381
|
+
push_command.should_receive(:invoke).with(:bind_service, :app => app).exactly(bind_times).times do
|
|
382
|
+
call_count += 1
|
|
383
|
+
app.stub(:services).and_return(service_instances.first(call_count))
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
should_ask("Bind another service?", anything).exactly(bind_times).times do
|
|
387
|
+
call_count < bind_times
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
subject
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
it "stops asking if there are no more services to bind" do
|
|
394
|
+
bind_times = service_instances.size
|
|
395
|
+
call_count = 0
|
|
396
|
+
|
|
397
|
+
should_ask("Bind other services to application?", anything) { true }
|
|
398
|
+
|
|
399
|
+
push_command.should_receive(:invoke).with(:bind_service, :app => app).exactly(bind_times).times do
|
|
400
|
+
call_count += 1
|
|
401
|
+
app.stub(:services).and_return(service_instances.first(call_count))
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
should_ask("Bind another service?", anything).exactly(bind_times-1).times { true }
|
|
405
|
+
|
|
406
|
+
subject
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
context "when there are no services" do
|
|
410
|
+
let(:service_instances) { [] }
|
|
411
|
+
|
|
412
|
+
it "does not ask to bind anything" do
|
|
413
|
+
dont_allow_ask
|
|
414
|
+
subject
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
end
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
describe "#start_app" do
|
|
421
|
+
let(:app) { build(:app, :client => client) }
|
|
422
|
+
subject { push_command.start_app(app) }
|
|
423
|
+
|
|
424
|
+
context "when the start flag is provided" do
|
|
425
|
+
let(:inputs) { {:start => true} }
|
|
426
|
+
|
|
427
|
+
it "invokes the start command" do
|
|
428
|
+
push_command.should_receive(:invoke).with(:start, :app => app)
|
|
429
|
+
subject
|
|
430
|
+
end
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
context "when the start flag is not provided" do
|
|
434
|
+
let(:inputs) { {:start => false} }
|
|
435
|
+
|
|
436
|
+
it "invokes the start command" do
|
|
437
|
+
push_command.should_not_receive(:invoke).with(:start, anything)
|
|
438
|
+
subject
|
|
439
|
+
end
|
|
440
|
+
end
|
|
441
|
+
end
|
|
442
|
+
end
|
|
443
|
+
end
|
|
444
|
+
end
|