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
data/Rakefile
CHANGED
|
@@ -1 +1,12 @@
|
|
|
1
|
-
require "
|
|
1
|
+
require "rake"
|
|
2
|
+
require "rspec/core/rake_task"
|
|
3
|
+
|
|
4
|
+
specfile, _ = Dir["*.gemspec"]
|
|
5
|
+
SPEC = Gem::Specification.load(specfile)
|
|
6
|
+
CURRENT_VERSION = SPEC.version.to_s.freeze
|
|
7
|
+
|
|
8
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
9
|
+
task :default => :spec
|
|
10
|
+
|
|
11
|
+
# looking for a way to push gems? check out the new frontend-release git repo!
|
|
12
|
+
# git@github.com:pivotal-vmware/frontend-release.git
|
data/bin/cf
CHANGED
data/lib/cf.rb
CHANGED
data/lib/cf/cli.rb
CHANGED
|
@@ -1,270 +1,469 @@
|
|
|
1
|
-
require "
|
|
2
|
-
require "
|
|
3
|
-
require "
|
|
4
|
-
require "
|
|
1
|
+
require "yaml"
|
|
2
|
+
require "socket"
|
|
3
|
+
require "net/http"
|
|
4
|
+
require "multi_json"
|
|
5
|
+
require "fileutils"
|
|
6
|
+
|
|
7
|
+
require "mothership"
|
|
8
|
+
|
|
9
|
+
require "cfoundry"
|
|
10
|
+
|
|
11
|
+
require "cf/constants"
|
|
12
|
+
require "cf/errors"
|
|
13
|
+
require "cf/spacing"
|
|
14
|
+
|
|
15
|
+
require "cf/cli/help"
|
|
16
|
+
require "cf/cli/interactive"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
$cf_asked_auth = false
|
|
5
20
|
|
|
6
21
|
module CF
|
|
7
|
-
class CLI <
|
|
8
|
-
|
|
22
|
+
class CLI < Mothership
|
|
23
|
+
include CF::Interactive
|
|
24
|
+
include CF::Spacing
|
|
9
25
|
|
|
10
|
-
|
|
11
|
-
:
|
|
26
|
+
option :help, :desc => "Show command usage", :alias => "-h",
|
|
27
|
+
:default => false
|
|
12
28
|
|
|
13
|
-
|
|
14
|
-
:
|
|
29
|
+
option :proxy, :desc => "Run this command as another user (admin)", :alias => "-u",
|
|
30
|
+
:value => :email
|
|
15
31
|
|
|
16
|
-
|
|
17
|
-
:
|
|
32
|
+
option :version, :desc => "Print version number", :alias => "-v",
|
|
33
|
+
:default => false
|
|
18
34
|
|
|
19
|
-
|
|
20
|
-
:
|
|
35
|
+
option :verbose, :desc => "Print extra information", :alias => "-V",
|
|
36
|
+
:default => false
|
|
21
37
|
|
|
22
|
-
|
|
38
|
+
option :force, :desc => "Skip interaction when possible", :alias => "-f",
|
|
39
|
+
:type => :boolean, :default => proc { input[:script] }
|
|
23
40
|
|
|
24
|
-
desc "
|
|
25
|
-
|
|
41
|
+
option :debug, :desc => "Print full stack trace (instead of crash log)",
|
|
42
|
+
:type => :boolean, :default => false
|
|
26
43
|
|
|
27
|
-
desc "
|
|
28
|
-
|
|
44
|
+
option :quiet, :desc => "Simplify output format", :alias => "-q",
|
|
45
|
+
:type => :boolean, :default => proc { input[:script] }
|
|
29
46
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
flag(:services)
|
|
33
|
-
def info
|
|
34
|
-
info =
|
|
35
|
-
with_progress("Getting target information") do
|
|
36
|
-
client.info
|
|
37
|
-
end
|
|
47
|
+
option :script, :desc => "Shortcut for --quiet and --force",
|
|
48
|
+
:type => :boolean, :default => proc { !$stdout.tty? }
|
|
38
49
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
info["frameworks"].each do |_, f|
|
|
42
|
-
f["runtimes"].each do |r|
|
|
43
|
-
runtimes[r["name"]] = r
|
|
44
|
-
end
|
|
45
|
-
end
|
|
50
|
+
option :color, :desc => "Use colorful output",
|
|
51
|
+
:type => :boolean, :default => proc { !input[:quiet] }
|
|
46
52
|
|
|
47
|
-
|
|
53
|
+
option :trace, :desc => "Show API traffic", :alias => "-t",
|
|
54
|
+
:default => false
|
|
48
55
|
|
|
49
|
-
if simple_output?
|
|
50
|
-
runtimes.each do |r|
|
|
51
|
-
puts r["name"]
|
|
52
|
-
end
|
|
53
|
-
return
|
|
54
|
-
end
|
|
55
56
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
57
|
+
def default_action
|
|
58
|
+
if input[:version]
|
|
59
|
+
line "cf #{VERSION}"
|
|
60
|
+
else
|
|
61
|
+
super
|
|
62
|
+
end
|
|
63
|
+
end
|
|
62
64
|
|
|
63
|
-
|
|
65
|
+
def check_target
|
|
66
|
+
unless client && client.target
|
|
67
|
+
fail "Please select a target with 'cf target'."
|
|
64
68
|
end
|
|
69
|
+
end
|
|
65
70
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
71
|
+
def check_logged_in
|
|
72
|
+
unless client.logged_in?
|
|
73
|
+
if force?
|
|
74
|
+
fail "Please log in with 'cf login'."
|
|
75
|
+
else
|
|
76
|
+
line c("Please log in first to proceed.", :warning)
|
|
77
|
+
line
|
|
78
|
+
invoke :login
|
|
79
|
+
invalidate_client
|
|
72
80
|
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
73
83
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
end
|
|
84
|
+
def precondition
|
|
85
|
+
check_target
|
|
86
|
+
check_logged_in
|
|
78
87
|
|
|
79
|
-
|
|
80
|
-
|
|
88
|
+
unless client.current_organization
|
|
89
|
+
fail "Please select an organization with 'cf target --ask-org'."
|
|
90
|
+
end
|
|
81
91
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
puts " description: #{versions[0]["description"]}"
|
|
87
|
-
puts " type: #{versions[0]["type"]}"
|
|
88
|
-
end
|
|
92
|
+
unless client.current_space
|
|
93
|
+
fail "Please select a space with 'cf target --ask-space'."
|
|
94
|
+
end
|
|
95
|
+
end
|
|
89
96
|
|
|
90
|
-
|
|
97
|
+
def wrap_errors
|
|
98
|
+
yield
|
|
99
|
+
rescue CFoundry::Timeout => e
|
|
100
|
+
err(e.message)
|
|
101
|
+
rescue Interrupt
|
|
102
|
+
exit_status 130
|
|
103
|
+
rescue Mothership::Error
|
|
104
|
+
raise
|
|
105
|
+
rescue UserError => e
|
|
106
|
+
log_error(e)
|
|
107
|
+
err e.message
|
|
108
|
+
rescue SystemExit
|
|
109
|
+
raise
|
|
110
|
+
rescue CFoundry::Forbidden, CFoundry::InvalidAuthToken => e
|
|
111
|
+
if !$cf_asked_auth
|
|
112
|
+
$cf_asked_auth = true
|
|
113
|
+
|
|
114
|
+
line
|
|
115
|
+
line c("Not authenticated! Try logging in:", :warning)
|
|
116
|
+
|
|
117
|
+
# TODO: there's no color here; global flags not being passed
|
|
118
|
+
# through (mothership bug?)
|
|
119
|
+
invoke :login
|
|
120
|
+
|
|
121
|
+
retry
|
|
91
122
|
end
|
|
92
123
|
|
|
93
|
-
|
|
124
|
+
log_error(e)
|
|
94
125
|
|
|
95
|
-
|
|
96
|
-
puts ""
|
|
97
|
-
puts "target: #{b(client.target)}"
|
|
98
|
-
puts " version: #{info["version"]}"
|
|
99
|
-
puts " support: #{info["support"]}"
|
|
126
|
+
err "Denied: #{e.description}"
|
|
100
127
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
puts "user: #{b(info["user"])}"
|
|
104
|
-
puts " usage:"
|
|
128
|
+
rescue Exception => e
|
|
129
|
+
log_error(e)
|
|
105
130
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
131
|
+
msg = e.class.name
|
|
132
|
+
msg << ": #{e}" unless e.to_s.empty?
|
|
133
|
+
msg << "\nFor more information, see #{CF::CRASH_FILE}"
|
|
134
|
+
err msg
|
|
135
|
+
|
|
136
|
+
raise if debug?
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def execute(cmd, argv, global = {})
|
|
140
|
+
if input[:help]
|
|
141
|
+
invoke :help, :command => cmd.name.to_s
|
|
142
|
+
else
|
|
143
|
+
wrap_errors do
|
|
144
|
+
@command = cmd
|
|
145
|
+
precondition
|
|
146
|
+
|
|
147
|
+
save_token_if_it_changes do
|
|
148
|
+
super
|
|
113
149
|
end
|
|
114
150
|
end
|
|
115
151
|
end
|
|
116
152
|
end
|
|
117
153
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
if url.nil?
|
|
121
|
-
display_target
|
|
122
|
-
return
|
|
123
|
-
end
|
|
154
|
+
def save_token_if_it_changes
|
|
155
|
+
return yield unless client && client.token
|
|
124
156
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
unless force?
|
|
129
|
-
# check that the target is valid
|
|
130
|
-
CFoundry::Client.new(target).info
|
|
131
|
-
end
|
|
157
|
+
before_token = client.token
|
|
158
|
+
|
|
159
|
+
yield
|
|
132
160
|
|
|
133
|
-
|
|
161
|
+
after_token = client.token
|
|
162
|
+
|
|
163
|
+
return unless after_token
|
|
164
|
+
|
|
165
|
+
if before_token != after_token
|
|
166
|
+
info = target_info
|
|
167
|
+
info[:token] = after_token.auth_header
|
|
168
|
+
save_target_info(info)
|
|
134
169
|
end
|
|
135
170
|
end
|
|
136
171
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
ask("Email")
|
|
140
|
-
}
|
|
141
|
-
flag(:password)
|
|
142
|
-
# TODO: implement new authentication scheme
|
|
143
|
-
def login(email = nil)
|
|
144
|
-
unless simple_output?
|
|
145
|
-
display_target
|
|
146
|
-
puts ""
|
|
147
|
-
end
|
|
172
|
+
def log_error(e)
|
|
173
|
+
ensure_config_dir
|
|
148
174
|
|
|
149
|
-
|
|
150
|
-
|
|
175
|
+
msg = e.class.name
|
|
176
|
+
msg << ": #{e}" unless e.to_s.empty?
|
|
151
177
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
178
|
+
crash_file = File.expand_path(CF::CRASH_FILE)
|
|
179
|
+
|
|
180
|
+
FileUtils.mkdir_p(File.dirname(crash_file))
|
|
181
|
+
|
|
182
|
+
File.open(crash_file, "w") do |f|
|
|
183
|
+
f.puts "Time of crash:"
|
|
184
|
+
f.puts " #{Time.now}"
|
|
185
|
+
f.puts ""
|
|
186
|
+
f.puts msg
|
|
187
|
+
f.puts ""
|
|
188
|
+
|
|
189
|
+
if e.respond_to?(:request_trace)
|
|
190
|
+
f.puts "<<<"
|
|
191
|
+
f.puts e.request_trace
|
|
159
192
|
end
|
|
160
193
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
return if force?
|
|
194
|
+
if e.respond_to?(:response_trace)
|
|
195
|
+
f.puts e.response_trace
|
|
196
|
+
f.puts ">>>"
|
|
197
|
+
f.puts ""
|
|
198
|
+
end
|
|
167
199
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
200
|
+
cf_dir = File.expand_path("../../../..", __FILE__) + "/"
|
|
201
|
+
e.backtrace.each do |loc|
|
|
202
|
+
if loc =~ /\/gems\//
|
|
203
|
+
f.puts loc.sub(/.*\/gems\//, "")
|
|
204
|
+
else
|
|
205
|
+
f.puts loc.sub(cf_dir, "")
|
|
171
206
|
end
|
|
172
207
|
end
|
|
173
208
|
end
|
|
174
|
-
ensure
|
|
175
|
-
$exit_status = 1 if not authenticated
|
|
176
209
|
end
|
|
177
210
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
with_progress("Logging out") do
|
|
181
|
-
remove_token
|
|
182
|
-
end
|
|
211
|
+
def quiet?
|
|
212
|
+
input[:quiet]
|
|
183
213
|
end
|
|
184
214
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
def
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
215
|
+
def force?
|
|
216
|
+
input[:force]
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def debug?
|
|
220
|
+
!!input[:debug]
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def color_enabled?
|
|
224
|
+
input[:color]
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def verbose?
|
|
228
|
+
input[:verbose]
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def user_colors
|
|
232
|
+
return @user_colors if @user_colors
|
|
198
233
|
|
|
199
|
-
|
|
200
|
-
password = input(:password)
|
|
234
|
+
colors = File.expand_path(COLORS_FILE)
|
|
201
235
|
|
|
202
|
-
|
|
203
|
-
|
|
236
|
+
@user_colors = super.dup
|
|
237
|
+
|
|
238
|
+
# most terminal schemes are stupid, so use cyan instead
|
|
239
|
+
@user_colors.each do |k, v|
|
|
240
|
+
if v == :blue
|
|
241
|
+
@user_colors[k] = :cyan
|
|
242
|
+
end
|
|
204
243
|
end
|
|
205
244
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
245
|
+
if File.exists?(colors)
|
|
246
|
+
YAML.load_file(colors).each do |k, v|
|
|
247
|
+
@user_colors[k.to_sym] = v.to_sym
|
|
209
248
|
end
|
|
210
249
|
end
|
|
250
|
+
|
|
251
|
+
@user_colors
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def err(msg, status = 1)
|
|
255
|
+
$stderr.puts c(msg, :error)
|
|
256
|
+
exit_status status
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def fail(msg)
|
|
260
|
+
raise UserError, msg
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def table(headers, rows)
|
|
264
|
+
tabular(
|
|
265
|
+
!quiet? && headers.collect { |h| h && b(h) },
|
|
266
|
+
*rows)
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
def name_list(xs)
|
|
270
|
+
if xs.empty?
|
|
271
|
+
d("none")
|
|
272
|
+
else
|
|
273
|
+
xs.collect { |x| c(x.name, :name) }.join(", ")
|
|
274
|
+
end
|
|
211
275
|
end
|
|
212
276
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
277
|
+
def sane_target_url(url)
|
|
278
|
+
unless url =~ /^https?:\/\//
|
|
279
|
+
begin
|
|
280
|
+
TCPSocket.new(url, Net::HTTP.https_default_port)
|
|
281
|
+
url = "https://#{url}"
|
|
282
|
+
rescue Errno::ECONNREFUSED, SocketError, Timeout::Error
|
|
283
|
+
url = "http://#{url}"
|
|
218
284
|
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
url.gsub(/\/$/, "")
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def target_file
|
|
291
|
+
one_of(CF::TARGET_FILE, CF::OLD_TARGET_FILE)
|
|
292
|
+
end
|
|
219
293
|
|
|
220
|
-
|
|
294
|
+
def tokens_file
|
|
295
|
+
one_of(CF::TOKENS_FILE, CF::OLD_TOKENS_FILE)
|
|
296
|
+
end
|
|
221
297
|
|
|
222
|
-
|
|
223
|
-
|
|
298
|
+
def one_of(*paths)
|
|
299
|
+
paths.each do |p|
|
|
300
|
+
exp = File.expand_path(p)
|
|
301
|
+
return exp if File.exist? exp
|
|
224
302
|
end
|
|
225
303
|
|
|
226
|
-
|
|
227
|
-
|
|
304
|
+
File.expand_path(paths.first)
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def client_target
|
|
308
|
+
if File.exists?(target_file)
|
|
309
|
+
File.read(target_file).chomp
|
|
228
310
|
end
|
|
229
311
|
end
|
|
230
312
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
313
|
+
def ensure_config_dir
|
|
314
|
+
config = File.expand_path(CF::CONFIG_DIR)
|
|
315
|
+
FileUtils.mkdir_p(config) unless File.exist? config
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
def set_target(url)
|
|
319
|
+
ensure_config_dir
|
|
320
|
+
|
|
321
|
+
File.open(File.expand_path(CF::TARGET_FILE), "w") do |f|
|
|
322
|
+
f.write(sane_target_url(url))
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
invalidate_client
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def targets_info
|
|
329
|
+
new_toks = File.expand_path(CF::TOKENS_FILE)
|
|
330
|
+
old_toks = File.expand_path(CF::OLD_TOKENS_FILE)
|
|
331
|
+
|
|
332
|
+
info =
|
|
333
|
+
if File.exist? new_toks
|
|
334
|
+
YAML.load_file(new_toks)
|
|
335
|
+
elsif File.exist? old_toks
|
|
336
|
+
MultiJson.load(File.read(old_toks))
|
|
236
337
|
end
|
|
237
338
|
|
|
238
|
-
|
|
239
|
-
|
|
339
|
+
info ||= {}
|
|
340
|
+
|
|
341
|
+
normalize_targets_info(info)
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
def normalize_targets_info(info_by_url)
|
|
345
|
+
info_by_url.reduce({}) do |hash, pair|
|
|
346
|
+
key, value = pair
|
|
347
|
+
hash[key] = value.is_a?(String) ? { :token => value } : value
|
|
348
|
+
hash
|
|
240
349
|
end
|
|
241
350
|
end
|
|
242
351
|
|
|
243
|
-
|
|
352
|
+
def target_info(target = client_target)
|
|
353
|
+
targets_info[target] || {}
|
|
354
|
+
end
|
|
244
355
|
|
|
245
|
-
def
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
356
|
+
def save_targets(ts)
|
|
357
|
+
ensure_config_dir
|
|
358
|
+
|
|
359
|
+
File.open(File.expand_path(CF::TOKENS_FILE), "w") do |io|
|
|
360
|
+
YAML.dump(ts, io)
|
|
250
361
|
end
|
|
251
362
|
end
|
|
252
363
|
|
|
253
|
-
def
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
364
|
+
def save_target_info(info, target = client_target)
|
|
365
|
+
ts = targets_info
|
|
366
|
+
ts[target] = info
|
|
367
|
+
save_targets(ts)
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
def remove_target_info(target = client_target)
|
|
371
|
+
ts = targets_info
|
|
372
|
+
ts.delete target
|
|
373
|
+
save_targets(ts)
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
def invalidate_client
|
|
377
|
+
@@client = nil
|
|
378
|
+
client
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
def client(target = client_target)
|
|
382
|
+
return @@client if defined?(@@client) && @@client
|
|
383
|
+
return unless target
|
|
384
|
+
|
|
385
|
+
info = target_info(target)
|
|
386
|
+
token = info[:token] && CFoundry::AuthToken.from_hash(info)
|
|
387
|
+
|
|
388
|
+
@@client =
|
|
389
|
+
case info[:version]
|
|
390
|
+
when 2
|
|
391
|
+
fail "User switching not implemented." if input[:proxy]
|
|
392
|
+
CFoundry::V2::Client.new(target, token)
|
|
393
|
+
when 1
|
|
394
|
+
CFoundry::V1::Client.new(target, token)
|
|
395
|
+
else
|
|
396
|
+
CFoundry::Client.new(target, token)
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
unless @@client.is_a?(CFoundry::V2::Client)
|
|
400
|
+
# TODO
|
|
401
|
+
fail "V1 targets are no longer supported."
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
@@client.proxy = input[:proxy]
|
|
405
|
+
@@client.trace = input[:trace]
|
|
406
|
+
|
|
407
|
+
uri = URI.parse(target)
|
|
408
|
+
@@client.log = File.expand_path("#{LOGS_DIR}/#{uri.host}.log")
|
|
409
|
+
|
|
410
|
+
unless info.key? :version
|
|
411
|
+
info[:version] = @@client.version
|
|
412
|
+
save_target_info(info, target)
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
if org = info[:organization]
|
|
416
|
+
@@client.current_organization = @@client.organization(org)
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
if space = info[:space]
|
|
420
|
+
@@client.current_space = @@client.space(space)
|
|
260
421
|
end
|
|
422
|
+
|
|
423
|
+
@@client
|
|
424
|
+
rescue CFoundry::InvalidTarget
|
|
261
425
|
end
|
|
262
426
|
|
|
263
|
-
def
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
427
|
+
def fail_unknown(display, name)
|
|
428
|
+
fail("Unknown #{display} '#{name}'.")
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
class << self
|
|
432
|
+
def client
|
|
433
|
+
@@client
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
def client=(c)
|
|
437
|
+
@@client = c
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
private
|
|
441
|
+
|
|
442
|
+
def find_by_name(display, &blk)
|
|
443
|
+
proc { |name, *args|
|
|
444
|
+
choices, _ = args
|
|
445
|
+
choices ||= instance_exec(&blk) if block_given?
|
|
446
|
+
|
|
447
|
+
choices.find { |c| c.name == name } ||
|
|
448
|
+
fail_unknown(display, name)
|
|
449
|
+
}
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
def by_name(what, display = what)
|
|
453
|
+
proc { |name, *_|
|
|
454
|
+
client.send(:"#{what}_by_name", name) ||
|
|
455
|
+
fail_unknown(display, name)
|
|
456
|
+
}
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
def find_by_name_insensitive(display, &blk)
|
|
460
|
+
proc { |name, *args|
|
|
461
|
+
choices, _ = args
|
|
462
|
+
choices ||= instance_exec(&blk) if block_given?
|
|
463
|
+
|
|
464
|
+
choices.find { |c| c.name.upcase == name.upcase } ||
|
|
465
|
+
fail_unknown(display, name)
|
|
466
|
+
}
|
|
268
467
|
end
|
|
269
468
|
end
|
|
270
469
|
end
|