af 0.3.22 → 0.5.0.beta.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.
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