cf 0.1.5 → 0.6.0.rc1
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.
- data/LICENSE +1277 -30
- data/Rakefile +12 -1
- data/bin/cf +0 -3
- data/lib/cf.rb +6 -0
- data/lib/cf/cli.rb +389 -190
- data/lib/cf/cli/app/app.rb +45 -0
- data/lib/cf/cli/app/apps.rb +99 -0
- data/lib/cf/cli/app/base.rb +90 -0
- data/lib/cf/cli/app/crashes.rb +42 -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 +78 -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 +105 -0
- data/lib/cf/cli/app/push/create.rb +149 -0
- data/lib/cf/cli/app/push/interactions.rb +94 -0
- data/lib/cf/cli/app/push/sync.rb +64 -0
- data/lib/cf/cli/app/rename.rb +35 -0
- data/lib/cf/cli/app/restart.rb +20 -0
- data/lib/cf/cli/app/scale.rb +69 -0
- data/lib/cf/cli/app/start.rb +143 -0
- data/lib/cf/cli/app/stats.rb +67 -0
- data/lib/cf/cli/app/stop.rb +27 -0
- data/lib/cf/cli/domain/base.rb +8 -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 +105 -0
- data/lib/cf/cli/organization/base.rb +12 -0
- data/lib/cf/cli/organization/create.rb +32 -0
- data/lib/cf/cli/organization/delete.rb +73 -0
- data/lib/cf/cli/organization/org.rb +45 -0
- data/lib/cf/cli/organization/orgs.rb +35 -0
- data/lib/cf/cli/organization/rename.rb +36 -0
- data/lib/cf/cli/route/base.rb +8 -0
- data/lib/cf/cli/route/map.rb +70 -0
- data/lib/cf/cli/route/routes.rb +26 -0
- data/lib/cf/cli/route/unmap.rb +62 -0
- data/lib/cf/cli/service/base.rb +8 -0
- data/lib/cf/cli/service/bind.rb +44 -0
- data/lib/cf/cli/service/create.rb +107 -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/services.rb +99 -0
- data/lib/cf/cli/service/unbind.rb +38 -0
- data/lib/cf/cli/space/base.rb +19 -0
- data/lib/cf/cli/space/create.rb +63 -0
- data/lib/cf/cli/space/delete.rb +95 -0
- data/lib/cf/cli/space/rename.rb +39 -0
- data/lib/cf/cli/space/space.rb +64 -0
- data/lib/cf/cli/space/spaces.rb +55 -0
- data/lib/cf/cli/space/switch.rb +16 -0
- data/lib/cf/cli/start/base.rb +93 -0
- data/lib/cf/cli/start/colors.rb +13 -0
- data/lib/cf/cli/start/info.rb +124 -0
- data/lib/cf/cli/start/login.rb +94 -0
- data/lib/cf/cli/start/logout.rb +17 -0
- data/lib/cf/cli/start/target.rb +69 -0
- data/lib/cf/cli/start/target_interactions.rb +37 -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 +39 -0
- data/lib/cf/cli/user/passwd.rb +43 -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 -7
- data/lib/cf/detect.rb +113 -48
- data/lib/cf/errors.rb +17 -0
- data/lib/cf/plugin.rb +28 -12
- 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 +1 -1
- 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 +6 -0
- data/spec/assets/specker_runner/specker_runner_input.rb +6 -0
- data/spec/assets/specker_runner/specker_runner_pause.rb +5 -0
- data/spec/cf/cli/app/base_spec.rb +17 -0
- data/spec/cf/cli/app/delete_spec.rb +188 -0
- data/spec/cf/cli/app/instances_spec.rb +65 -0
- data/spec/cf/cli/app/push/create_spec.rb +661 -0
- data/spec/cf/cli/app/push_spec.rb +369 -0
- data/spec/cf/cli/app/rename_spec.rb +104 -0
- data/spec/cf/cli/app/scale_spec.rb +75 -0
- data/spec/cf/cli/app/start_spec.rb +208 -0
- data/spec/cf/cli/app/stats_spec.rb +68 -0
- data/spec/cf/cli/domain/map_spec.rb +130 -0
- data/spec/cf/cli/domain/unmap_spec.rb +69 -0
- data/spec/cf/cli/organization/orgs_spec.rb +108 -0
- data/spec/cf/cli/organization/rename_spec.rb +113 -0
- data/spec/cf/cli/route/map_spec.rb +121 -0
- data/spec/cf/cli/route/unmap_spec.rb +155 -0
- data/spec/cf/cli/service/bind_spec.rb +25 -0
- data/spec/cf/cli/service/delete_spec.rb +22 -0
- data/spec/cf/cli/service/rename_spec.rb +105 -0
- data/spec/cf/cli/service/service_spec.rb +23 -0
- data/spec/cf/cli/service/unbind_spec.rb +25 -0
- data/spec/cf/cli/space/create_spec.rb +93 -0
- data/spec/cf/cli/space/rename_spec.rb +102 -0
- data/spec/cf/cli/space/spaces_spec.rb +104 -0
- data/spec/cf/cli/space/switch_space_spec.rb +55 -0
- data/spec/cf/cli/start/info_spec.rb +160 -0
- data/spec/cf/cli/start/login_spec.rb +142 -0
- data/spec/cf/cli/start/logout_spec.rb +50 -0
- data/spec/cf/cli/start/target_spec.rb +123 -0
- data/spec/cf/cli/user/create_spec.rb +54 -0
- data/spec/cf/cli/user/passwd_spec.rb +102 -0
- data/spec/cf/cli/user/register_spec.rb +140 -0
- data/spec/cf/cli_spec.rb +442 -0
- data/spec/cf/detect_spec.rb +54 -0
- data/spec/console_app_specker/console_app_specker_matchers_spec.rb +173 -0
- data/spec/console_app_specker/specker_runner_spec.rb +167 -0
- data/spec/features/account_lifecycle_spec.rb +85 -0
- data/spec/features/login_spec.rb +66 -0
- data/spec/features/push_flow_spec.rb +125 -0
- data/spec/features/switching_targets_spec.rb +32 -0
- data/spec/spec_helper.rb +72 -0
- data/spec/support/command_helper.rb +81 -0
- data/spec/support/config_helper.rb +15 -0
- data/spec/support/console_app_specker_matchers.rb +86 -0
- data/spec/support/fake_home_dir.rb +55 -0
- data/spec/support/interact_helper.rb +29 -0
- data/spec/support/shared_examples/errors.rb +40 -0
- data/spec/support/shared_examples/input.rb +14 -0
- data/spec/support/specker_runner.rb +80 -0
- data/spec/support/tracking_expector.rb +71 -0
- metadata +427 -66
- data/lib/cf/cli/app.rb +0 -595
- data/lib/cf/cli/command.rb +0 -444
- data/lib/cf/cli/dots.rb +0 -133
- data/lib/cf/cli/service.rb +0 -112
- data/lib/cf/cli/user.rb +0 -71
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require "cf/cli/space/switch"
|
|
3
|
+
|
|
4
|
+
describe CF::Space::Switch do
|
|
5
|
+
let(:space_to_switch_to) { spaces.last }
|
|
6
|
+
let(:spaces) { fake_list(:space, 3) }
|
|
7
|
+
let(:organization) { fake(:organization, :spaces => spaces) }
|
|
8
|
+
let(:client) { fake_client(:current_organization => organization, :spaces => spaces) }
|
|
9
|
+
|
|
10
|
+
before do
|
|
11
|
+
any_instance_of described_class do |cli|
|
|
12
|
+
stub(cli).client { client }
|
|
13
|
+
stub(cli).precondition { nil }
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe 'metadata' do
|
|
18
|
+
let(:command) { Mothership.commands[:switch_space] }
|
|
19
|
+
|
|
20
|
+
describe 'command' do
|
|
21
|
+
subject { command }
|
|
22
|
+
its(:description) { should eq "Switch to a space" }
|
|
23
|
+
it { expect(Mothership::Help.group(:spaces)).to include(subject) }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
include_examples 'inputs must have descriptions'
|
|
27
|
+
|
|
28
|
+
describe 'arguments' do
|
|
29
|
+
subject { command.arguments }
|
|
30
|
+
it 'has the correct argument order' do
|
|
31
|
+
should eq([{ :type => :normal, :value => nil, :name => :name }])
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
subject { cf %W[--no-quiet switch-space #{space_to_switch_to.name} --no-color] }
|
|
37
|
+
|
|
38
|
+
context "when the space exists" do
|
|
39
|
+
it "switches to that space" do
|
|
40
|
+
any_instance_of(Mothership) do |m|
|
|
41
|
+
mock(m).invoke(:target, {:space => space_to_switch_to})
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
subject
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
context "when the space does not exist" do
|
|
49
|
+
let(:space_to_switch_to) { fake(:space, :name => "unique-name") }
|
|
50
|
+
|
|
51
|
+
it_behaves_like "an error that gets passed through",
|
|
52
|
+
:with_exception => CF::UserError,
|
|
53
|
+
:with_message => "The space unique-name does not exist, please create the space first."
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe CF::Start::Info do
|
|
4
|
+
let(:frameworks) { false }
|
|
5
|
+
let(:runtimes) { false }
|
|
6
|
+
let(:services) { false }
|
|
7
|
+
let(:all) { false }
|
|
8
|
+
|
|
9
|
+
let(:client) do
|
|
10
|
+
fake_client :frameworks => fake_list(:framework, 3),
|
|
11
|
+
:runtimes => fake_list(:runtime, 3),
|
|
12
|
+
:services => fake_list(:service, 3),
|
|
13
|
+
:token => CFoundry::AuthToken.new("bearer some-access-token")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
let(:target_info) do
|
|
17
|
+
{ :description => "Some description",
|
|
18
|
+
:version => 2,
|
|
19
|
+
:support => "http://example.com"
|
|
20
|
+
}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
before do
|
|
24
|
+
any_instance_of described_class do |cli|
|
|
25
|
+
stub(cli).client { client }
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe 'metadata' do
|
|
30
|
+
let(:command) { Mothership.commands[:info] }
|
|
31
|
+
|
|
32
|
+
describe 'command' do
|
|
33
|
+
subject { command }
|
|
34
|
+
its(:description) { should eq "Display information on the current target, user, etc." }
|
|
35
|
+
it { expect(Mothership::Help.group(:start)).to include(subject) }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
include_examples 'inputs must have descriptions'
|
|
39
|
+
|
|
40
|
+
describe 'flags' do
|
|
41
|
+
subject { command.flags }
|
|
42
|
+
|
|
43
|
+
its(["-f"]) { should eq :frameworks }
|
|
44
|
+
its(["-r"]) { should eq :runtimes }
|
|
45
|
+
its(["-s"]) { should eq :services }
|
|
46
|
+
its(["-a"]) { should eq :all }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe 'arguments' do
|
|
50
|
+
subject { command.arguments }
|
|
51
|
+
it { should be_empty }
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
subject { cf %W[info --#{bool_flag(:frameworks)} --#{bool_flag(:runtimes)} --#{bool_flag(:services)} --#{bool_flag(:all)} --no-force --no-quiet] }
|
|
57
|
+
|
|
58
|
+
context 'when given no flags' do
|
|
59
|
+
it "displays target information" do
|
|
60
|
+
mock(client).info { target_info }
|
|
61
|
+
|
|
62
|
+
subject
|
|
63
|
+
|
|
64
|
+
stdout.rewind
|
|
65
|
+
expect(stdout.readline).to eq "Some description\n"
|
|
66
|
+
expect(stdout.readline).to eq "\n"
|
|
67
|
+
expect(stdout.readline).to eq "target: #{client.target}\n"
|
|
68
|
+
expect(stdout.readline).to eq " version: 2\n"
|
|
69
|
+
expect(stdout.readline).to eq " support: http://example.com\n"
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context 'when given --frameworks' do
|
|
74
|
+
let(:frameworks) { true }
|
|
75
|
+
|
|
76
|
+
it 'does not grab /info' do
|
|
77
|
+
dont_allow(client).info
|
|
78
|
+
subject
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it 'lists frameworks on the target' do
|
|
82
|
+
subject
|
|
83
|
+
|
|
84
|
+
stdout.rewind
|
|
85
|
+
expect(stdout.readline).to match /Getting frameworks.*OK/
|
|
86
|
+
expect(stdout.readline).to eq "\n"
|
|
87
|
+
expect(stdout.readline).to match /framework\s+description/
|
|
88
|
+
|
|
89
|
+
client.frameworks.sort_by(&:name).each do |f|
|
|
90
|
+
expect(stdout.readline).to match /#{f.name}\s+#{f.description}/
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
context 'when given --runtimes' do
|
|
96
|
+
let(:runtimes) { true }
|
|
97
|
+
|
|
98
|
+
it 'does not grab /info' do
|
|
99
|
+
dont_allow(client).info
|
|
100
|
+
subject
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it 'lists runtimes on the target' do
|
|
104
|
+
subject
|
|
105
|
+
|
|
106
|
+
stdout.rewind
|
|
107
|
+
expect(stdout.readline).to match /Getting runtimes.*OK/
|
|
108
|
+
expect(stdout.readline).to eq "\n"
|
|
109
|
+
expect(stdout.readline).to match /runtime\s+description/
|
|
110
|
+
|
|
111
|
+
client.runtimes.sort_by(&:name).each do |r|
|
|
112
|
+
expect(stdout.readline).to match /#{r.name}\s+#{r.description}/
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
context 'when given --services' do
|
|
118
|
+
let(:services) { true }
|
|
119
|
+
|
|
120
|
+
it 'does not grab /info' do
|
|
121
|
+
dont_allow(client).info
|
|
122
|
+
subject
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it 'lists services on the target' do
|
|
126
|
+
subject
|
|
127
|
+
|
|
128
|
+
stdout.rewind
|
|
129
|
+
expect(stdout.readline).to match /Getting services.*OK/
|
|
130
|
+
expect(stdout.readline).to eq "\n"
|
|
131
|
+
expect(stdout.readline).to match /service\s+version\s+provider\s+plans\s+description/
|
|
132
|
+
|
|
133
|
+
client.services.sort_by(&:label).each do |s|
|
|
134
|
+
expect(stdout.readline).to match /#{s.label}\s+#{s.version}\s+#{s.provider}.+#{s.description}/
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
context 'when given --all' do
|
|
140
|
+
let(:all) { true }
|
|
141
|
+
|
|
142
|
+
it 'combines --frameworks --runtimes and --services' do
|
|
143
|
+
mock(client).info { target_info }
|
|
144
|
+
|
|
145
|
+
subject
|
|
146
|
+
|
|
147
|
+
stdout.rewind
|
|
148
|
+
expect(stdout.readline).to match /Getting runtimes.*OK/
|
|
149
|
+
expect(stdout.readline).to match /Getting frameworks.*OK/
|
|
150
|
+
expect(stdout.readline).to match /Getting services.*OK/
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
context 'when there is no target' do
|
|
155
|
+
let(:client) { nil }
|
|
156
|
+
it_behaves_like "an error that gets passed through",
|
|
157
|
+
:with_exception => CF::UserError,
|
|
158
|
+
:with_message => "Please select a target with 'cf target'."
|
|
159
|
+
end
|
|
160
|
+
end
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
command CF::Start::Login do
|
|
4
|
+
let(:client) { fake_client :organizations => [] }
|
|
5
|
+
|
|
6
|
+
describe 'metadata' do
|
|
7
|
+
let(:command) { Mothership.commands[:login] }
|
|
8
|
+
|
|
9
|
+
describe 'command' do
|
|
10
|
+
subject { command }
|
|
11
|
+
its(:description) { should eq "Authenticate with the target" }
|
|
12
|
+
specify { expect(Mothership::Help.group(:start)).to include(subject) }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
include_examples 'inputs must have descriptions'
|
|
16
|
+
|
|
17
|
+
describe 'flags' do
|
|
18
|
+
subject { command.flags }
|
|
19
|
+
|
|
20
|
+
its(["-o"]) { should eq :organization }
|
|
21
|
+
its(["--org"]) { should eq :organization }
|
|
22
|
+
its(["--email"]) { should eq :username }
|
|
23
|
+
its(["-s"]) { should eq :space }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
describe 'arguments' do
|
|
27
|
+
subject(:arguments) { command.arguments }
|
|
28
|
+
it 'have the correct commands' do
|
|
29
|
+
expect(arguments).to eq [{:type => :optional, :value => :email, :name => :username}]
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe "running the command" do
|
|
35
|
+
stub_home_dir_with { "#{SPEC_ROOT}/fixtures/fake_home_dirs/new" }
|
|
36
|
+
|
|
37
|
+
let(:auth_token) { CFoundry::AuthToken.new("bearer some-new-access-token", "some-new-refresh-token") }
|
|
38
|
+
let(:tokens_yaml) { YAML.load_file(File.expand_path(tokens_file_path)) }
|
|
39
|
+
let(:tokens_file_path) { '~/.cf/tokens.yml' }
|
|
40
|
+
let(:organizations) { [] }
|
|
41
|
+
|
|
42
|
+
before do
|
|
43
|
+
stub(client).login("my-username", "my-password") { auth_token }
|
|
44
|
+
stub(client).login_prompts do
|
|
45
|
+
{
|
|
46
|
+
:username => ["text", "Username"],
|
|
47
|
+
:password => ["password", "8-digit PIN"]
|
|
48
|
+
}
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
subject { cf ["login"] }
|
|
53
|
+
|
|
54
|
+
it "logs in with the provided credentials and saves the token data to the YAML file" do
|
|
55
|
+
stub_ask("Username", {}) { "my-username" }
|
|
56
|
+
stub_ask("8-digit PIN", {:echo => "*", :forget => true}) { "my-password" }
|
|
57
|
+
|
|
58
|
+
subject
|
|
59
|
+
|
|
60
|
+
expect(tokens_yaml["https://api.some-domain.com"][:token]).to eq("bearer some-new-access-token")
|
|
61
|
+
expect(tokens_yaml["https://api.some-domain.com"][:refresh_token]).to eq("some-new-refresh-token")
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
context "with space and org in the token file" do
|
|
65
|
+
before do
|
|
66
|
+
write_token_file(:space => "space-id-1", :organization => "organization-id-1")
|
|
67
|
+
stub_ask("Username", {}) { "my-username" }
|
|
68
|
+
stub_ask("8-digit PIN", {:echo => "*", :forget => true}) { "my-password" }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
context "when the user has no organizations" do
|
|
72
|
+
it "clears the org and space param from the token file" do
|
|
73
|
+
subject
|
|
74
|
+
|
|
75
|
+
expect(tokens_yaml["https://api.some-domain.com"][:space]).to be_nil
|
|
76
|
+
expect(tokens_yaml["https://api.some-domain.com"][:organization]).to be_nil
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
context "when the user has an organization, but no spaces" do
|
|
81
|
+
let(:client) {
|
|
82
|
+
fake_client :organizations => organizations,
|
|
83
|
+
:token => CFoundry::AuthToken.new("bearer some-access-token")
|
|
84
|
+
}
|
|
85
|
+
let(:organization) { fake :organization, :users => [user] }
|
|
86
|
+
let(:user) { fake :user }
|
|
87
|
+
|
|
88
|
+
shared_examples_for :method_clearing_the_token_file do
|
|
89
|
+
it "sets the new organization in the token file" do
|
|
90
|
+
subject
|
|
91
|
+
expect(tokens_yaml["https://api.some-domain.com"][:organization]).to eq(organizations.first.guid)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it "clears the space param from the token file" do
|
|
95
|
+
subject
|
|
96
|
+
expect(tokens_yaml["https://api.some-domain.com"][:space]).to be_nil
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
context "with one organization" do
|
|
101
|
+
let(:organizations) {
|
|
102
|
+
[ organization ]
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
it "does not prompt for an organization" do
|
|
106
|
+
dont_allow_ask("Organization", anything)
|
|
107
|
+
subject
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it_behaves_like :method_clearing_the_token_file
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
context "with multiple organizations" do
|
|
114
|
+
let(:organizations) {
|
|
115
|
+
[ organization, OpenStruct.new(:name => 'My Org 2', :guid => 'organization-id-2') ]
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
before do
|
|
119
|
+
stub_ask("Organization", anything) { organizations.first }
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it "prompts for organization" do
|
|
123
|
+
mock_ask("Organization", anything) { organizations.first }
|
|
124
|
+
subject
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it_behaves_like :method_clearing_the_token_file
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
context 'when there is no target' do
|
|
133
|
+
let(:client) { nil }
|
|
134
|
+
let(:stub_precondition?) { false }
|
|
135
|
+
|
|
136
|
+
it "tells the user to select a target" do
|
|
137
|
+
subject
|
|
138
|
+
expect(error_output).to say("Please select a target with 'cf target'.")
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe CF::Start::Logout do
|
|
4
|
+
let(:client) { fake_client }
|
|
5
|
+
|
|
6
|
+
before do
|
|
7
|
+
any_instance_of described_class do |cli|
|
|
8
|
+
stub(cli).client { client }
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe 'metadata' do
|
|
13
|
+
let(:command) { Mothership.commands[:logout] }
|
|
14
|
+
|
|
15
|
+
describe 'command' do
|
|
16
|
+
subject { command }
|
|
17
|
+
its(:description) { should eq "Log out from the target" }
|
|
18
|
+
it { expect(Mothership::Help.group(:start)).to include(subject) }
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe "running the command" do
|
|
23
|
+
subject { cf ["logout"] }
|
|
24
|
+
|
|
25
|
+
context "when there is a target" do
|
|
26
|
+
let(:info) { { client.target => "x", "abc" => "x" } }
|
|
27
|
+
|
|
28
|
+
before do
|
|
29
|
+
any_instance_of CF::CLI do |cli|
|
|
30
|
+
stub(cli).targets_info { info }
|
|
31
|
+
stub(cli).client_target { client.target }
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "removes the target info from the tokens file" do
|
|
36
|
+
expect {
|
|
37
|
+
subject
|
|
38
|
+
}.to change { info }.to("abc" => "x")
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
context "when there is no target" do
|
|
43
|
+
let(:client) { nil }
|
|
44
|
+
it_behaves_like "an error that gets passed through",
|
|
45
|
+
:with_exception => CF::UserError,
|
|
46
|
+
:with_message => "Please select a target with 'cf target'."
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require "webmock/rspec"
|
|
3
|
+
|
|
4
|
+
command CF::Start::Target do
|
|
5
|
+
let(:client) { fake_client :apps => [app] }
|
|
6
|
+
let(:app) { fake :app }
|
|
7
|
+
|
|
8
|
+
describe 'metadata' do
|
|
9
|
+
let(:command) { Mothership.commands[:target] }
|
|
10
|
+
|
|
11
|
+
describe 'command' do
|
|
12
|
+
subject { command }
|
|
13
|
+
its(:description) { should eq "Set or display the target cloud, organization, and space" }
|
|
14
|
+
specify { expect(Mothership::Help.group(:start)).to include(subject) }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
include_examples 'inputs must have descriptions'
|
|
18
|
+
|
|
19
|
+
describe 'flags' do
|
|
20
|
+
subject { command.flags }
|
|
21
|
+
|
|
22
|
+
its(["-o"]) { should eq :organization }
|
|
23
|
+
its(["--org"]) { should eq :organization }
|
|
24
|
+
its(["-s"]) { should eq :space }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe 'arguments' do
|
|
28
|
+
subject(:arguments) { command.arguments }
|
|
29
|
+
it 'have the correct commands' do
|
|
30
|
+
expect(arguments).to eq [{:type => :optional, :value => nil, :name => :url}]
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe 'running the command' do
|
|
36
|
+
stub_home_dir_with { "#{SPEC_ROOT}/fixtures/fake_home_dirs/new" }
|
|
37
|
+
|
|
38
|
+
context "when the user is authenticated and has an organization" do
|
|
39
|
+
let(:tokens_file_path) { '~/.cf/tokens.yml' }
|
|
40
|
+
let(:organizations) {
|
|
41
|
+
[ fake(:organization, :name => 'My Org', :guid => 'organization-id-1', :users => [user], :spaces => spaces),
|
|
42
|
+
fake(:organization, :name => 'My Org 2', :guid => 'organization-id-2') ]
|
|
43
|
+
}
|
|
44
|
+
let(:spaces) {
|
|
45
|
+
[ fake(:space, :name => 'Development', :guid => 'space-id-1'),
|
|
46
|
+
fake(:space, :name => 'Staging', :guid => 'space-id-2') ]
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let(:user) { stub! }
|
|
50
|
+
let(:organization) { organizations.first }
|
|
51
|
+
let(:client) do
|
|
52
|
+
fake_client :frameworks => fake_list(:framework, 3),
|
|
53
|
+
:organizations => organizations,
|
|
54
|
+
:token => CFoundry::AuthToken.new("bearer some-access-token")
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
before do
|
|
58
|
+
write_token_file({:space => "space-id-1", :organization => "organization-id-1"})
|
|
59
|
+
stub(client).current_user { user }
|
|
60
|
+
stub(client).organization { organization }
|
|
61
|
+
stub(client).current_organization { organization }
|
|
62
|
+
any_instance_of(described_class) do |instance|
|
|
63
|
+
stub(instance).client { client }
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
describe "switching the target" do
|
|
68
|
+
let(:target) { "some-valid-target.com" }
|
|
69
|
+
subject { cf ["target", target] }
|
|
70
|
+
|
|
71
|
+
context "when the target is not valid" do
|
|
72
|
+
before { WebMock.stub_request(:get, "http://#{target}/info").to_return(:body => "{}") }
|
|
73
|
+
|
|
74
|
+
it "should still be able to switch to a valid target after that" do
|
|
75
|
+
subject
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
context "when the target is valid but the connection is refused" do
|
|
80
|
+
it "shows a pretty error message" do
|
|
81
|
+
any_instance_of(CFoundry::Client) do |cli|
|
|
82
|
+
stub(cli).info { raise CFoundry::TargetRefused, "foo" }
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
subject
|
|
86
|
+
expect(error_output).to say("Target refused connection.")
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
context "when the uri is malformed" do
|
|
91
|
+
it "shows a pretty error message" do
|
|
92
|
+
any_instance_of(CFoundry::Client) do |cli|
|
|
93
|
+
stub(cli).info { raise CFoundry::InvalidTarget.new(target) }
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
subject
|
|
97
|
+
expect(error_output).to say("Invalid target URI.")
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
describe "switching the space" do
|
|
103
|
+
let(:space) { spaces.last }
|
|
104
|
+
let(:tokens_yaml) { YAML.load_file(File.expand_path(tokens_file_path)) }
|
|
105
|
+
let(:tokens_file_path) { '~/.cf/tokens.yml' }
|
|
106
|
+
|
|
107
|
+
def run_command
|
|
108
|
+
cf %W[target -s #{space.name}]
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it "should not reprompt for organization" do
|
|
112
|
+
dont_allow_ask("Organization", anything)
|
|
113
|
+
run_command
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it "sets the space param in the token file" do
|
|
117
|
+
run_command
|
|
118
|
+
expect(tokens_yaml["https://api.some-domain.com"][:space]).to be == 'space-id-2'
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|