af 0.3.22 → 0.5.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (157) hide show
  1. checksums.yaml +14 -6
  2. data/LICENSE +1277 -24
  3. data/Rakefile +24 -87
  4. data/bin/af +7 -2
  5. data/lib/af/version.rb +3 -0
  6. data/lib/vmc.rb +7 -2
  7. data/lib/vmc/cli.rb +475 -0
  8. data/lib/vmc/cli/app/app.rb +45 -0
  9. data/lib/vmc/cli/app/apps.rb +105 -0
  10. data/lib/vmc/cli/app/base.rb +82 -0
  11. data/lib/vmc/cli/app/crashes.rb +46 -0
  12. data/lib/vmc/cli/app/delete.rb +95 -0
  13. data/lib/vmc/cli/app/deprecated.rb +11 -0
  14. data/lib/vmc/cli/app/env.rb +78 -0
  15. data/lib/vmc/cli/app/files.rb +137 -0
  16. data/lib/vmc/cli/app/health.rb +26 -0
  17. data/lib/vmc/cli/app/instances.rb +53 -0
  18. data/lib/vmc/cli/app/logs.rb +76 -0
  19. data/lib/vmc/cli/app/push.rb +107 -0
  20. data/lib/vmc/cli/app/push/create.rb +150 -0
  21. data/lib/vmc/cli/app/push/interactions.rb +100 -0
  22. data/lib/vmc/cli/app/push/sync.rb +64 -0
  23. data/lib/vmc/cli/app/rename.rb +39 -0
  24. data/lib/vmc/cli/app/restart.rb +20 -0
  25. data/lib/vmc/cli/app/scale.rb +71 -0
  26. data/lib/vmc/cli/app/start.rb +93 -0
  27. data/lib/vmc/cli/app/stats.rb +67 -0
  28. data/lib/vmc/cli/app/stop.rb +27 -0
  29. data/lib/vmc/cli/domain/base.rb +12 -0
  30. data/lib/vmc/cli/domain/domains.rb +40 -0
  31. data/lib/vmc/cli/domain/map.rb +55 -0
  32. data/lib/vmc/cli/domain/unmap.rb +56 -0
  33. data/lib/vmc/cli/help.rb +16 -0
  34. data/lib/vmc/cli/interactive.rb +105 -0
  35. data/lib/vmc/cli/organization/base.rb +14 -0
  36. data/lib/vmc/cli/organization/create.rb +32 -0
  37. data/lib/vmc/cli/organization/delete.rb +73 -0
  38. data/lib/vmc/cli/organization/org.rb +45 -0
  39. data/lib/vmc/cli/organization/orgs.rb +35 -0
  40. data/lib/vmc/cli/organization/rename.rb +36 -0
  41. data/lib/vmc/cli/route/base.rb +12 -0
  42. data/lib/vmc/cli/route/map.rb +80 -0
  43. data/lib/vmc/cli/route/routes.rb +26 -0
  44. data/lib/vmc/cli/route/unmap.rb +94 -0
  45. data/lib/vmc/cli/service/base.rb +8 -0
  46. data/lib/vmc/cli/service/bind.rb +44 -0
  47. data/lib/vmc/cli/service/create.rb +126 -0
  48. data/lib/vmc/cli/service/delete.rb +86 -0
  49. data/lib/vmc/cli/service/rename.rb +35 -0
  50. data/lib/vmc/cli/service/service.rb +42 -0
  51. data/lib/vmc/cli/service/services.rb +115 -0
  52. data/lib/vmc/cli/service/unbind.rb +38 -0
  53. data/lib/vmc/cli/space/base.rb +21 -0
  54. data/lib/vmc/cli/space/create.rb +56 -0
  55. data/lib/vmc/cli/space/delete.rb +95 -0
  56. data/lib/vmc/cli/space/rename.rb +39 -0
  57. data/lib/vmc/cli/space/space.rb +64 -0
  58. data/lib/vmc/cli/space/spaces.rb +55 -0
  59. data/lib/vmc/cli/space/take.rb +16 -0
  60. data/lib/vmc/cli/start/base.rb +80 -0
  61. data/lib/vmc/cli/start/colors.rb +13 -0
  62. data/lib/vmc/cli/start/info.rb +122 -0
  63. data/lib/vmc/cli/start/login.rb +92 -0
  64. data/lib/vmc/cli/start/logout.rb +13 -0
  65. data/lib/vmc/cli/start/target.rb +64 -0
  66. data/lib/vmc/cli/start/target_interactions.rb +37 -0
  67. data/lib/vmc/cli/start/targets.rb +16 -0
  68. data/lib/vmc/cli/user/base.rb +29 -0
  69. data/lib/vmc/cli/user/create.rb +39 -0
  70. data/lib/vmc/cli/user/delete.rb +25 -0
  71. data/lib/vmc/cli/user/passwd.rb +50 -0
  72. data/lib/vmc/cli/user/register.rb +42 -0
  73. data/lib/vmc/cli/user/users.rb +32 -0
  74. data/lib/vmc/constants.rb +13 -0
  75. data/lib/vmc/detect.rb +134 -0
  76. data/lib/vmc/errors.rb +17 -0
  77. data/lib/vmc/plugin.rb +56 -0
  78. data/lib/vmc/spacing.rb +89 -0
  79. data/lib/vmc/spec_helper.rb +1 -0
  80. data/lib/vmc/test_support.rb +4 -0
  81. data/lib/vmc/test_support/command_helper.rb +32 -0
  82. data/lib/vmc/test_support/common_input_examples.rb +14 -0
  83. data/lib/vmc/test_support/fake_home_dir.rb +16 -0
  84. data/lib/vmc/test_support/interact_helper.rb +29 -0
  85. data/lib/vmc/version.rb +3 -0
  86. data/spec/assets/hello-sinatra/Gemfile +3 -0
  87. data/spec/assets/hello-sinatra/main.rb +6 -0
  88. data/spec/features/new_user_flow_spec.rb +71 -0
  89. data/spec/spec_helper.rb +63 -0
  90. data/spec/vmc/cli/app/base_spec.rb +17 -0
  91. data/spec/vmc/cli/app/delete_spec.rb +188 -0
  92. data/spec/vmc/cli/app/instances_spec.rb +65 -0
  93. data/spec/vmc/cli/app/push/create_spec.rb +571 -0
  94. data/spec/vmc/cli/app/push_spec.rb +369 -0
  95. data/spec/vmc/cli/app/rename_spec.rb +104 -0
  96. data/spec/vmc/cli/app/scale_spec.rb +81 -0
  97. data/spec/vmc/cli/app/stats_spec.rb +62 -0
  98. data/spec/vmc/cli/domain/map_spec.rb +140 -0
  99. data/spec/vmc/cli/domain/unmap_spec.rb +73 -0
  100. data/spec/vmc/cli/organization/orgs_spec.rb +108 -0
  101. data/spec/vmc/cli/organization/rename_spec.rb +113 -0
  102. data/spec/vmc/cli/route/map_spec.rb +138 -0
  103. data/spec/vmc/cli/route/unmap_spec.rb +215 -0
  104. data/spec/vmc/cli/service/bind_spec.rb +25 -0
  105. data/spec/vmc/cli/service/delete_spec.rb +22 -0
  106. data/spec/vmc/cli/service/rename_spec.rb +105 -0
  107. data/spec/vmc/cli/service/service_spec.rb +23 -0
  108. data/spec/vmc/cli/service/unbind_spec.rb +25 -0
  109. data/spec/vmc/cli/space/rename_spec.rb +102 -0
  110. data/spec/vmc/cli/space/spaces_spec.rb +104 -0
  111. data/spec/vmc/cli/start/info_spec.rb +153 -0
  112. data/spec/vmc/cli/start/login_spec.rb +71 -0
  113. data/spec/vmc/cli/user/create_spec.rb +54 -0
  114. data/spec/vmc/cli/user/passwd_spec.rb +102 -0
  115. data/spec/vmc/cli/user/register_spec.rb +148 -0
  116. data/spec/vmc/cli_spec.rb +448 -0
  117. data/spec/vmc/detect_spec.rb +54 -0
  118. metadata +231 -124
  119. data/README.md +0 -155
  120. data/caldecott_helper/Gemfile +0 -10
  121. data/caldecott_helper/Gemfile.lock +0 -48
  122. data/caldecott_helper/server.rb +0 -43
  123. data/config/clients.yml +0 -17
  124. data/config/micro/offline.conf +0 -2
  125. data/config/micro/paths.yml +0 -22
  126. data/config/micro/refresh_ip.rb +0 -20
  127. data/lib/cli.rb +0 -48
  128. data/lib/cli/commands/admin.rb +0 -81
  129. data/lib/cli/commands/apps.rb +0 -1358
  130. data/lib/cli/commands/base.rb +0 -233
  131. data/lib/cli/commands/manifest.rb +0 -56
  132. data/lib/cli/commands/micro.rb +0 -115
  133. data/lib/cli/commands/misc.rb +0 -147
  134. data/lib/cli/commands/services.rb +0 -217
  135. data/lib/cli/commands/user.rb +0 -70
  136. data/lib/cli/config.rb +0 -176
  137. data/lib/cli/console_helper.rb +0 -163
  138. data/lib/cli/core_ext.rb +0 -122
  139. data/lib/cli/errors.rb +0 -19
  140. data/lib/cli/file_helper.rb +0 -123
  141. data/lib/cli/frameworks.rb +0 -265
  142. data/lib/cli/manifest_helper.rb +0 -316
  143. data/lib/cli/runner.rb +0 -633
  144. data/lib/cli/services_helper.rb +0 -104
  145. data/lib/cli/tunnel_helper.rb +0 -336
  146. data/lib/cli/usage.rb +0 -129
  147. data/lib/cli/version.rb +0 -7
  148. data/lib/cli/zip_util.rb +0 -102
  149. data/lib/vmc/client.rb +0 -574
  150. data/lib/vmc/const.rb +0 -27
  151. data/lib/vmc/micro.rb +0 -56
  152. data/lib/vmc/micro/switcher/base.rb +0 -97
  153. data/lib/vmc/micro/switcher/darwin.rb +0 -19
  154. data/lib/vmc/micro/switcher/dummy.rb +0 -15
  155. data/lib/vmc/micro/switcher/linux.rb +0 -16
  156. data/lib/vmc/micro/switcher/windows.rb +0 -31
  157. data/lib/vmc/micro/vmrun.rb +0 -158
data/Rakefile CHANGED
@@ -1,101 +1,38 @@
1
- require 'rake'
2
- require 'spec/rake/spectask'
1
+ require "rake"
2
+ require "rspec/core/rake_task"
3
3
 
4
- desc "Run specs"
5
- task :spec => :build do
6
- Spec::Rake::SpecTask.new('spec') do |t|
7
- t.spec_opts = %w(-fs -c)
8
- t.spec_files = FileList['spec/**/*_spec.rb']
9
- end
10
- end
4
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
5
+ require "vmc/version"
11
6
 
12
- desc "Synonym for spec"
13
- task :test => :spec
14
- desc "Synonym for spec"
15
- task :tests => :spec
7
+ RSpec::Core::RakeTask.new(:spec)
16
8
  task :default => :spec
17
9
 
18
- def tests_path
19
- if @tests_path == nil
20
- @tests_path = File.join(Dir.pwd, "spec/assets/tests")
10
+ namespace :deploy do
11
+ def last_staging_sha
12
+ `git rev-parse latest-staging`.strip
21
13
  end
22
- @tests_path
23
- end
24
- TESTS_PATH = tests_path
25
-
26
- BUILD_ARTIFACT = File.join(Dir.pwd, "spec/assets/.build")
27
14
 
28
- TESTS_TO_BUILD = ["#{TESTS_PATH}/java_web/java_tiny_app",
29
- # "#{TESTS_PATH}/grails/guestbook",
30
- "#{TESTS_PATH}/lift/hello_lift",
31
- "#{TESTS_PATH}/spring/roo-guestbook",
32
- "#{TESTS_PATH}/spring/spring-osgi-hello",
33
- "#{TESTS_PATH}/standalone/java_app",
34
- "#{TESTS_PATH}/standalone/python_app"
35
- ]
36
-
37
- desc "Build the tests. If the git hash associated with the test assets has not changed, nothing is built. To force a build, invoke 'rake build[--force]'"
38
- task :build, [:force] do |t, args|
39
- sh('bundle install')
40
- sh('git submodule update --init')
41
- puts "\nBuilding tests"
42
- if build_required? args.force
43
- ENV['MAVEN_OPTS']="-XX:MaxPermSize=256M"
44
- TESTS_TO_BUILD.each do |test|
45
- puts "\tBuilding '#{test}'"
46
- Dir.chdir test do
47
- sh('mvn package -DskipTests') do |success, exit_code|
48
- unless success
49
- clear_build_artifact
50
- do_mvn_clean('-q')
51
- fail "\tFailed to build #{test} - aborting build"
52
- end
53
- end
54
- end
55
- puts "\tCompleted building '#{test}'"
56
- end
57
- save_git_hash
58
- else
59
- puts "Built artifacts in sync with test assets - no build required"
15
+ def last_release_sha
16
+ `git rev-parse latest-release`.strip
60
17
  end
61
- end
62
18
 
63
- desc "Clean the build artifacts"
64
- task :clean do
65
- puts "\nCleaning tests"
66
- clear_build_artifact
67
- TESTS_TO_BUILD.each do |test|
68
- puts "\tCleaning '#{test}'"
69
- Dir.chdir test do
70
- do_mvn_clean
71
- end
72
- puts "\tCompleted cleaning '#{test}'"
19
+ def last_staging_ref_was_released?
20
+ last_staging_sha == last_release_sha
73
21
  end
74
- end
75
22
 
76
- def build_required? (force_build=nil)
77
- if File.exists?(BUILD_ARTIFACT) == false or (force_build and force_build == "--force")
78
- return true
23
+ task :staging, :version do |_, args|
24
+ sh "gem bump --push #{"--version #{args.version}" if args.version}" if last_staging_ref_was_released?
25
+ sh "git tag -f latest-staging"
26
+ sh "git push origin :latest-staging"
27
+ sh "git push origin latest-staging"
79
28
  end
80
- Dir.chdir(tests_path) do
81
- saved_git_hash = IO.readlines(BUILD_ARTIFACT)[0].split[0]
82
- git_hash = `git rev-parse --short=8 --verify HEAD`
83
- saved_git_hash.to_s.strip != git_hash.to_s.strip
84
- end
85
- end
86
29
 
87
- def save_git_hash
88
- Dir.chdir(tests_path) do
89
- git_hash = `git rev-parse --short=8 --verify HEAD`
90
- File.open(BUILD_ARTIFACT, 'w') {|f| f.puts("#{git_hash}")}
30
+ task :gem do
31
+ sh "git fetch"
32
+ sh "git checkout #{last_staging_sha}"
33
+ sh "gem release --tag"
34
+ sh "git tag -f latest-release"
35
+ sh "git push origin :latest-release"
36
+ sh "git push origin latest-release"
91
37
  end
92
38
  end
93
-
94
- def clear_build_artifact
95
- puts "\tClearing build artifact #{BUILD_ARTIFACT}"
96
- File.unlink BUILD_ARTIFACT if File.exists? BUILD_ARTIFACT
97
- end
98
-
99
- def do_mvn_clean options=nil
100
- sh("mvn clean #{options}")
101
- end
data/bin/af CHANGED
@@ -1,6 +1,11 @@
1
1
  #!/usr/bin/env ruby
2
+ # vim: ft=ruby
2
3
 
3
- require File.expand_path('../../lib/cli', __FILE__)
4
+ require "rubygems"
4
5
 
5
- VMC::Cli::Runner.run(ARGV.dup)
6
+ require "vmc"
7
+ require "vmc/plugin"
6
8
 
9
+ VMC::Plugin.load_all
10
+
11
+ VMC::CLI.start(ARGV)
@@ -0,0 +1,3 @@
1
+ module AF
2
+ VERSION = "0.5.0.beta.1".freeze
3
+ end
data/lib/vmc.rb CHANGED
@@ -1,3 +1,8 @@
1
- module VMC; end
1
+ require "vmc/version"
2
2
 
3
- require 'vmc/client'
3
+ require "vmc/cli"
4
+
5
+ command_files = "../vmc/cli/{app,route,domain,organization,space,service,start,user}/*.rb"
6
+ Dir[File.expand_path(command_files, __FILE__)].each do |file|
7
+ require file unless File.basename(file) == 'base.rb'
8
+ end
@@ -0,0 +1,475 @@
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 "vmc/constants"
12
+ require "vmc/errors"
13
+ require "vmc/spacing"
14
+
15
+ require "vmc/cli/help"
16
+ require "vmc/cli/interactive"
17
+
18
+ require "af/version"
19
+
20
+ $vmc_asked_auth = false
21
+
22
+ module VMC
23
+ class CLI < Mothership
24
+ include VMC::Interactive
25
+ include VMC::Spacing
26
+
27
+ option :help, :desc => "Show command usage", :alias => "-h",
28
+ :default => false
29
+
30
+ option :proxy, :desc => "Act as another user (admin)", :alias => "-u",
31
+ :value => :email
32
+
33
+ option :version, :desc => "Print version number", :alias => "-v",
34
+ :default => false
35
+
36
+ option :verbose, :desc => "Print extra information", :alias => "-V",
37
+ :default => false
38
+
39
+ option :force, :desc => "Skip interaction when possible", :alias => "-f",
40
+ :type => :boolean, :default => proc { input[:script] }
41
+
42
+ option :debug, :desc => "Print full stack trace (instead of crash log)",
43
+ :type => :boolean, :default => false
44
+
45
+ option :quiet, :desc => "Simplify output format", :alias => "-q",
46
+ :type => :boolean, :default => proc { input[:script] }
47
+
48
+ option :script, :desc => "Shortcut for --quiet and --force",
49
+ :type => :boolean, :default => proc { !$stdout.tty? }
50
+
51
+ option :color, :desc => "Use colorful output",
52
+ :type => :boolean, :default => proc { !input[:quiet] }
53
+
54
+ option :trace, :desc => "Show API traffic", :alias => "-t",
55
+ :default => false
56
+
57
+
58
+ def default_action
59
+ if input[:version]
60
+ line "af #{AF::VERSION}"
61
+ else
62
+ super
63
+ end
64
+ end
65
+
66
+ def check_target
67
+ unless File.exists? target_file
68
+ fail "Please select a target with 'af target'."
69
+ end
70
+ end
71
+
72
+ def check_logged_in
73
+ unless client.logged_in?
74
+ if force?
75
+ fail "Please log in with 'af login'."
76
+ else
77
+ line c("Please log in first to proceed.", :warning)
78
+ line
79
+ invoke :login
80
+ invalidate_client
81
+ end
82
+ end
83
+ end
84
+
85
+ def precondition
86
+ check_target
87
+ check_logged_in
88
+
89
+ return unless v2?
90
+
91
+ unless client.current_organization
92
+ fail "Please select an organization with 'af target --ask-org'."
93
+ end
94
+
95
+ unless client.current_space
96
+ fail "Please select a space with 'af target --ask-space'."
97
+ end
98
+ end
99
+
100
+ def wrap_errors
101
+ yield
102
+ rescue CFoundry::Timeout => e
103
+ err(e.message)
104
+ rescue Interrupt
105
+ exit_status 130
106
+ rescue Mothership::Error
107
+ raise
108
+ rescue UserError => e
109
+ log_error(e)
110
+ err e.message
111
+ rescue SystemExit
112
+ raise
113
+ rescue CFoundry::Forbidden, CFoundry::InvalidAuthToken => e
114
+ if !$vmc_asked_auth
115
+ $vmc_asked_auth = true
116
+
117
+ line
118
+ line c("Not authenticated! Try logging in:", :warning)
119
+
120
+ # TODO: there's no color here; global flags not being passed
121
+ # through (mothership bug?)
122
+ invoke :login
123
+
124
+ retry
125
+ end
126
+
127
+ log_error(e)
128
+
129
+ err "Denied: #{e.description}"
130
+
131
+ rescue Exception => e
132
+ log_error(e)
133
+
134
+ msg = e.class.name
135
+ msg << ": #{e}" unless e.to_s.empty?
136
+ msg << "\nFor more information, see #{VMC::CRASH_FILE}"
137
+ err msg
138
+
139
+ raise if debug?
140
+ end
141
+
142
+ def execute(cmd, argv, global = {})
143
+ if input[:help]
144
+ invoke :help, :command => cmd.name.to_s
145
+ else
146
+ wrap_errors do
147
+ @command = cmd
148
+ precondition
149
+
150
+ save_token_if_it_changes do
151
+ super
152
+ end
153
+ end
154
+ end
155
+ end
156
+
157
+ def save_token_if_it_changes
158
+ return yield unless client && client.token
159
+
160
+ before_token = client.token
161
+
162
+ yield
163
+
164
+ after_token = client.token
165
+
166
+ return unless after_token
167
+
168
+ if before_token != after_token
169
+ info = target_info
170
+ info[:token] = after_token.auth_header
171
+ save_target_info(info)
172
+ end
173
+ end
174
+
175
+ def log_error(e)
176
+ ensure_config_dir
177
+
178
+ msg = e.class.name
179
+ msg << ": #{e}" unless e.to_s.empty?
180
+
181
+ crash_file = File.expand_path(VMC::CRASH_FILE)
182
+
183
+ FileUtils.mkdir_p(File.dirname(crash_file))
184
+
185
+ File.open(crash_file, "w") do |f|
186
+ f.puts "Time of crash:"
187
+ f.puts " #{Time.now}"
188
+ f.puts ""
189
+ f.puts msg
190
+ f.puts ""
191
+
192
+ if e.respond_to?(:request_trace)
193
+ f.puts "<<<"
194
+ f.puts e.request_trace
195
+ end
196
+
197
+ if e.respond_to?(:response_trace)
198
+ f.puts e.response_trace
199
+ f.puts ">>>"
200
+ f.puts ""
201
+ end
202
+
203
+ vmc_dir = File.expand_path("../../../..", __FILE__) + "/"
204
+ e.backtrace.each do |loc|
205
+ if loc =~ /\/gems\//
206
+ f.puts loc.sub(/.*\/gems\//, "")
207
+ else
208
+ f.puts loc.sub(vmc_dir, "")
209
+ end
210
+ end
211
+ end
212
+ end
213
+
214
+ def quiet?
215
+ input[:quiet]
216
+ end
217
+
218
+ def force?
219
+ input[:force]
220
+ end
221
+
222
+ def debug?
223
+ !!input[:debug]
224
+ end
225
+
226
+ def color_enabled?
227
+ input[:color]
228
+ end
229
+
230
+ def verbose?
231
+ input[:verbose]
232
+ end
233
+
234
+ def user_colors
235
+ return @user_colors if @user_colors
236
+
237
+ colors = File.expand_path(COLORS_FILE)
238
+
239
+ @user_colors = super.dup
240
+
241
+ @user_colors[:infra] = :magenta
242
+
243
+ # most terminal schemes are stupid, so use cyan instead
244
+ @user_colors.each do |k, v|
245
+ if v == :blue
246
+ @user_colors[k] = :cyan
247
+ end
248
+ end
249
+
250
+ if File.exists?(colors)
251
+ YAML.load_file(colors).each do |k, v|
252
+ @user_colors[k.to_sym] = v.to_sym
253
+ end
254
+ end
255
+
256
+ @user_colors
257
+ end
258
+
259
+ def err(msg, status = 1)
260
+ $stderr.puts c(msg, :error)
261
+ exit_status status
262
+ end
263
+
264
+ def fail(msg)
265
+ raise UserError, msg
266
+ end
267
+
268
+ def table(headers, rows)
269
+ tabular(
270
+ !quiet? && headers.collect { |h| h && b(h) },
271
+ *rows)
272
+ end
273
+
274
+ def name_list(xs)
275
+ if xs.empty?
276
+ d("none")
277
+ else
278
+ xs.collect { |x| c(x.name, :name) }.join(", ")
279
+ end
280
+ end
281
+
282
+ def sane_target_url(url)
283
+ unless url =~ /^https?:\/\//
284
+ begin
285
+ TCPSocket.new(url, Net::HTTP.https_default_port)
286
+ url = "https://#{url}"
287
+ rescue Errno::ECONNREFUSED, SocketError, Timeout::Error
288
+ url = "http://#{url}"
289
+ end
290
+ end
291
+
292
+ url.gsub(/\/$/, "")
293
+ end
294
+
295
+ def target_file
296
+ one_of(VMC::TARGET_FILE, VMC::OLD_TARGET_FILE)
297
+ end
298
+
299
+ def tokens_file
300
+ one_of(VMC::TOKENS_FILE, VMC::OLD_TOKENS_FILE)
301
+ end
302
+
303
+ def one_of(*paths)
304
+ paths.each do |p|
305
+ exp = File.expand_path(p)
306
+ return exp if File.exist? exp
307
+ end
308
+
309
+ File.expand_path(paths.first)
310
+ end
311
+
312
+ def client_target
313
+ if File.exists?(target_file)
314
+ File.read(target_file).chomp
315
+ end
316
+ end
317
+
318
+ def ensure_config_dir
319
+ config = File.expand_path(VMC::CONFIG_DIR)
320
+ FileUtils.mkdir_p(config) unless File.exist? config
321
+ end
322
+
323
+ def set_target(url)
324
+ ensure_config_dir
325
+
326
+ File.open(File.expand_path(VMC::TARGET_FILE), "w") do |f|
327
+ f.write(sane_target_url(url))
328
+ end
329
+
330
+ invalidate_client
331
+ end
332
+
333
+ def targets_info
334
+ new_toks = File.expand_path(VMC::TOKENS_FILE)
335
+ old_toks = File.expand_path(VMC::OLD_TOKENS_FILE)
336
+
337
+ info = if File.exist? new_toks
338
+ YAML.load_file(new_toks)
339
+ elsif File.exist? old_toks
340
+ MultiJson.load(File.read(old_toks))
341
+ else
342
+ {}
343
+ end
344
+
345
+ normalize_targets_info(info)
346
+ end
347
+
348
+ def normalize_targets_info(info_by_url)
349
+ info_by_url.reduce({}) do |hash, pair|
350
+ key, value = pair
351
+ hash[key] = value.is_a?(String) ? {:token => value } : value
352
+ hash
353
+ end
354
+ end
355
+
356
+ def target_info(target = client_target)
357
+ targets_info[target] || {}
358
+ end
359
+
360
+ def save_targets(ts)
361
+ ensure_config_dir
362
+
363
+ File.open(File.expand_path(VMC::TOKENS_FILE), "w") do |io|
364
+ YAML.dump(ts, io)
365
+ end
366
+ end
367
+
368
+ def save_target_info(info, target = client_target)
369
+ ts = targets_info
370
+ ts[target] = info
371
+ save_targets(ts)
372
+ end
373
+
374
+ def remove_target_info(target = client_target)
375
+ ts = targets_info
376
+ ts.delete target
377
+ save_targets(ts)
378
+ end
379
+
380
+ def no_v2
381
+ fail "Not implemented for v2." if v2?
382
+ end
383
+
384
+ def v2?
385
+ client.version == 2
386
+ end
387
+
388
+ def invalidate_client
389
+ @@client = nil
390
+ client
391
+ end
392
+
393
+ def client(target = client_target)
394
+ return @@client if defined?(@@client) && @@client
395
+ return unless target
396
+
397
+ info = target_info(target)
398
+ token = info[:token] && CFoundry::AuthToken.from_hash(info)
399
+
400
+ @@client =
401
+ case info[:version]
402
+ when 2
403
+ CFoundry::V2::Client.new(target, token)
404
+ when 1
405
+ CFoundry::V1::Client.new(target, token)
406
+ else
407
+ CFoundry::Client.new(target, token)
408
+ end
409
+
410
+ @@client.proxy = input[:proxy]
411
+ @@client.trace = input[:trace]
412
+
413
+ uri = URI.parse(target)
414
+ @@client.log = File.expand_path("#{LOGS_DIR}/#{uri.host}.log")
415
+
416
+ unless info.key? :version
417
+ info[:version] = @@client.version
418
+ save_target_info(info, target)
419
+ end
420
+
421
+ if org = info[:organization]
422
+ @@client.current_organization = @@client.organization(org)
423
+ end
424
+
425
+ if space = info[:space]
426
+ @@client.current_space = @@client.space(space)
427
+ end
428
+
429
+ @@client
430
+ end
431
+
432
+ def fail_unknown(display, name)
433
+ fail("Unknown #{display} '#{name}'.")
434
+ end
435
+
436
+ class << self
437
+ def client
438
+ @@client
439
+ end
440
+
441
+ def client=(c)
442
+ @@client = c
443
+ end
444
+
445
+ private
446
+
447
+ def find_by_name(display, &blk)
448
+ proc { |name, *args|
449
+ choices, _ = args
450
+ choices ||= instance_exec(&blk) if block_given?
451
+
452
+ choices.find { |c| c.name == name } ||
453
+ fail_unknown(display, name)
454
+ }
455
+ end
456
+
457
+ def by_name(what, display = what)
458
+ proc { |name, *_|
459
+ client.send(:"#{what}_by_name", name) ||
460
+ fail_unknown(display, name)
461
+ }
462
+ end
463
+
464
+ def find_by_name_insensitive(display, &blk)
465
+ proc { |name, *args|
466
+ choices, _ = args
467
+ choices ||= instance_exec(&blk) if block_given?
468
+
469
+ choices.find { |c| c.name.upcase == name.upcase } ||
470
+ fail_unknown(display, name)
471
+ }
472
+ end
473
+ end
474
+ end
475
+ end