jdc 0.1.2 → 0.2.0
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 -24
- data/Rakefile +13 -0
- data/bin/jdc +12 -2
- data/lib/admin/README.md +15 -0
- data/lib/admin/curl.rb +60 -0
- data/lib/admin/guid.rb +89 -0
- data/lib/admin/plugin.rb +6 -0
- data/lib/admin/service_auth_token.rb +94 -0
- data/lib/admin/service_broker/add.rb +47 -0
- data/lib/admin/service_broker/service_brokers.rb +24 -0
- data/lib/admin/set_quota.rb +44 -0
- data/lib/console/README.md +8 -0
- data/lib/console/console.rb +187 -0
- data/lib/console/plugin.rb +33 -0
- data/lib/jdc/cli/app/app.rb +43 -0
- data/lib/jdc/cli/app/apps.rb +87 -0
- data/lib/jdc/cli/app/base.rb +72 -0
- data/lib/jdc/cli/app/delete.rb +95 -0
- data/lib/jdc/cli/app/deprecated.rb +11 -0
- data/lib/jdc/cli/app/env.rb +78 -0
- data/lib/jdc/cli/app/events.rb +45 -0
- data/lib/jdc/cli/app/files.rb +137 -0
- data/lib/jdc/cli/app/health.rb +26 -0
- data/lib/jdc/cli/app/instances.rb +53 -0
- data/lib/jdc/cli/app/logs.rb +76 -0
- data/lib/jdc/cli/app/push/create.rb +108 -0
- data/lib/jdc/cli/app/push/interactions.rb +86 -0
- data/lib/jdc/cli/app/push/sync.rb +57 -0
- data/lib/jdc/cli/app/push.rb +103 -0
- data/lib/jdc/cli/app/rename.rb +35 -0
- data/lib/jdc/cli/app/restart.rb +31 -0
- data/lib/jdc/cli/app/scale.rb +63 -0
- data/lib/jdc/cli/app/start.rb +161 -0
- data/lib/jdc/cli/app/stats.rb +67 -0
- data/lib/jdc/cli/app/stop.rb +27 -0
- data/lib/jdc/cli/domain/base.rb +9 -0
- data/lib/jdc/cli/domain/domains.rb +40 -0
- data/lib/jdc/cli/domain/map.rb +55 -0
- data/lib/jdc/cli/domain/unmap.rb +56 -0
- data/lib/jdc/cli/help.rb +15 -0
- data/lib/jdc/cli/interactive.rb +105 -0
- data/lib/jdc/cli/login_requirements.rb +15 -0
- data/lib/jdc/cli/organization/base.rb +14 -0
- data/lib/jdc/cli/organization/create.rb +37 -0
- data/lib/jdc/cli/organization/delete.rb +63 -0
- data/lib/jdc/cli/organization/org.rb +45 -0
- data/lib/jdc/cli/organization/orgs.rb +30 -0
- data/lib/jdc/cli/organization/rename.rb +37 -0
- data/lib/jdc/cli/populators/base.rb +16 -0
- data/lib/jdc/cli/populators/organization.rb +32 -0
- data/lib/jdc/cli/populators/populator_methods.rb +64 -0
- data/lib/jdc/cli/populators/space.rb +33 -0
- data/lib/jdc/cli/populators/target.rb +13 -0
- data/lib/jdc/cli/route/base.rb +9 -0
- data/lib/jdc/cli/route/delete.rb +28 -0
- data/lib/jdc/cli/route/map.rb +68 -0
- data/lib/jdc/cli/route/routes.rb +26 -0
- data/lib/jdc/cli/route/unmap.rb +56 -0
- data/lib/jdc/cli/service/base.rb +9 -0
- data/lib/jdc/cli/service/bind.rb +44 -0
- data/lib/jdc/cli/service/create.rb +159 -0
- data/lib/jdc/cli/service/delete.rb +83 -0
- data/lib/jdc/cli/service/rename.rb +36 -0
- data/lib/jdc/cli/service/service.rb +42 -0
- data/lib/jdc/cli/service/service_instance_helper.rb +99 -0
- data/lib/jdc/cli/service/services.rb +111 -0
- data/lib/jdc/cli/service/unbind.rb +37 -0
- data/lib/jdc/cli/space/base.rb +29 -0
- data/lib/jdc/cli/space/create.rb +67 -0
- data/lib/jdc/cli/space/delete.rb +56 -0
- data/lib/jdc/cli/space/rename.rb +38 -0
- data/lib/jdc/cli/space/space.rb +66 -0
- data/lib/jdc/cli/space/spaces.rb +57 -0
- data/lib/jdc/cli/space/switch.rb +19 -0
- data/lib/jdc/cli/start/base.rb +41 -0
- data/lib/jdc/cli/start/colors.rb +13 -0
- data/lib/jdc/cli/start/target.rb +50 -0
- data/lib/jdc/cli/start/target_prettifier.rb +17 -0
- data/lib/jdc/cli/start/targets.rb +16 -0
- data/lib/jdc/cli/user/base.rb +30 -0
- data/lib/jdc/cli/user/create.rb +52 -0
- data/lib/jdc/cli/user/passwd.rb +37 -0
- data/lib/jdc/cli/user/register.rb +43 -0
- data/lib/jdc/cli/user/users.rb +32 -0
- data/lib/jdc/cli.rb +544 -0
- data/lib/jdc/constants.rb +11 -0
- data/lib/jdc/errors.rb +19 -0
- data/lib/jdc/object_extensions.rb +15 -0
- data/lib/jdc/plugin.rb +56 -0
- data/lib/jdc/spacing.rb +89 -0
- data/lib/jdc/spec_helper.rb +1 -0
- data/lib/jdc/test_support.rb +6 -0
- data/lib/jdc/version.rb +3 -0
- data/lib/jdc.rb +15 -2
- data/lib/manifests/errors.rb +35 -0
- data/lib/manifests/loader/builder.rb +39 -0
- data/lib/manifests/loader/normalizer.rb +145 -0
- data/lib/manifests/loader/resolver.rb +79 -0
- data/lib/manifests/loader.rb +31 -0
- data/lib/manifests/manifests.rb +344 -0
- data/lib/manifests/plugin.rb +140 -0
- data/lib/micro/README.md +9 -0
- data/lib/micro/errors.rb +4 -0
- data/lib/{jdc → micro}/micro.rb +15 -15
- data/lib/micro/plugin.rb +197 -0
- data/lib/micro/switcher/base.rb +79 -0
- data/lib/{jdc/micro → micro}/switcher/darwin.rb +5 -3
- data/lib/{jdc/micro → micro}/switcher/dummy.rb +1 -1
- data/lib/micro/switcher/linux.rb +16 -0
- data/lib/{jdc/micro → micro}/switcher/windows.rb +5 -5
- data/lib/{jdc/micro → micro}/vmrun.rb +26 -19
- data/lib/tasks/gem_release.rake +42 -0
- data/lib/tunnel/README.md +29 -0
- data/{config → lib/tunnel/config}/clients.yml +2 -2
- data/lib/tunnel/helper-app/Gemfile +10 -0
- data/lib/tunnel/helper-app/Gemfile.lock +48 -0
- data/{caldecott_helper → lib/tunnel/helper-app}/server.rb +5 -5
- data/lib/tunnel/plugin.rb +183 -0
- data/lib/tunnel/tunnel.rb +295 -0
- metadata +319 -89
- data/README.md +0 -102
- data/config/micro/paths.yml +0 -22
- data/config/micro/refresh_ip.rb +0 -20
- data/lib/cli/commands/admin.rb +0 -58
- data/lib/cli/commands/apps.rb +0 -1129
- data/lib/cli/commands/base.rb +0 -228
- data/lib/cli/commands/manifest.rb +0 -56
- data/lib/cli/commands/micro.rb +0 -115
- data/lib/cli/commands/misc.rb +0 -126
- data/lib/cli/commands/services.rb +0 -178
- data/lib/cli/commands/user.rb +0 -14
- data/lib/cli/config.rb +0 -173
- data/lib/cli/console_helper.rb +0 -170
- data/lib/cli/core_ext.rb +0 -122
- data/lib/cli/errors.rb +0 -19
- data/lib/cli/frameworks.rb +0 -265
- data/lib/cli/manifest_helper.rb +0 -302
- data/lib/cli/runner.rb +0 -505
- data/lib/cli/services_helper.rb +0 -84
- data/lib/cli/tunnel_helper.rb +0 -332
- data/lib/cli/usage.rb +0 -86
- data/lib/cli/version.rb +0 -7
- data/lib/cli/zip_util.rb +0 -77
- data/lib/cli.rb +0 -53
- data/lib/jdc/client.rb +0 -457
- data/lib/jdc/const.rb +0 -25
- data/lib/jdc/micro/switcher/base.rb +0 -97
- data/lib/jdc/micro/switcher/linux.rb +0 -16
- data/lib/jdc/signature/version.rb +0 -27
- data/lib/jdc/signer.rb +0 -13
- data/lib/jdc/timer.rb +0 -12
data/lib/jdc/cli.rb
ADDED
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
require "yaml"
|
|
2
|
+
require "socket"
|
|
3
|
+
require "net/http"
|
|
4
|
+
require "multi_json"
|
|
5
|
+
require "fileutils"
|
|
6
|
+
|
|
7
|
+
require "mothership"
|
|
8
|
+
|
|
9
|
+
require "jfoundry"
|
|
10
|
+
|
|
11
|
+
require "jdc/constants"
|
|
12
|
+
require "jdc/errors"
|
|
13
|
+
require "jdc/spacing"
|
|
14
|
+
|
|
15
|
+
require "jdc/cli/help"
|
|
16
|
+
require "jdc/cli/interactive"
|
|
17
|
+
require "jdc/cli/login_requirements"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
$cf_asked_auth = false
|
|
21
|
+
|
|
22
|
+
module JDC
|
|
23
|
+
class CLI < Mothership
|
|
24
|
+
include JDC::Interactive
|
|
25
|
+
include JDC::Spacing
|
|
26
|
+
|
|
27
|
+
option :help, :desc => "Show command usage", :alias => "-h",
|
|
28
|
+
:default => false
|
|
29
|
+
|
|
30
|
+
option :http_proxy, :desc => "Connect though an http proxy server", :alias => "--http-proxy",
|
|
31
|
+
:value => :http_proxy
|
|
32
|
+
|
|
33
|
+
option :https_proxy, :desc => "Connect though an https proxy server", :alias => "--https-proxy",
|
|
34
|
+
:value => :https_proxy
|
|
35
|
+
|
|
36
|
+
option :version, :desc => "Print version number", :alias => "-v",
|
|
37
|
+
:default => false
|
|
38
|
+
|
|
39
|
+
option :verbose, :desc => "Print extra information", :alias => "-V",
|
|
40
|
+
:default => false
|
|
41
|
+
|
|
42
|
+
option :force, :desc => "Skip interaction when possible", :alias => "-f",
|
|
43
|
+
:type => :boolean, :default => proc { input[:script] }
|
|
44
|
+
|
|
45
|
+
option :debug, :desc => "Print full stack trace (instead of crash log)",
|
|
46
|
+
:type => :boolean, :default => false
|
|
47
|
+
|
|
48
|
+
option :quiet, :desc => "Simplify output format", :alias => "-q",
|
|
49
|
+
:type => :boolean, :default => proc { input[:script] }
|
|
50
|
+
|
|
51
|
+
option :script, :desc => "Shortcut for --quiet and --force",
|
|
52
|
+
:type => :boolean, :default => proc { !$stdout.tty? }
|
|
53
|
+
|
|
54
|
+
option :color, :desc => "Use colorful output",
|
|
55
|
+
:type => :boolean, :default => proc { !input[:quiet] }
|
|
56
|
+
|
|
57
|
+
option :trace, :desc => "Show API traffic", :alias => "-t",
|
|
58
|
+
:default => false
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def default_action
|
|
62
|
+
if input[:version]
|
|
63
|
+
line "jdc #{VERSION}"
|
|
64
|
+
else
|
|
65
|
+
super
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def check_key
|
|
70
|
+
unless ENV["ACCESS_KEY"]
|
|
71
|
+
fail "Please set the env ACCESS_KEY."
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
unless ENV["SECRET_KEY"]
|
|
75
|
+
fail "Please set the env SECRET_KEY."
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def check_target
|
|
80
|
+
unless client && client.target
|
|
81
|
+
fail "Please select a target with 'jdc target'."
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def check_organization_and_space
|
|
86
|
+
info = target_info(client.target)
|
|
87
|
+
|
|
88
|
+
info_changed = false
|
|
89
|
+
if (info.key? :organization) && info[:access_key] != ENV['ACCESS_KEY']
|
|
90
|
+
info.delete(:organization)
|
|
91
|
+
client.current_organization = nil
|
|
92
|
+
info_changed = true
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
if (info.key? :space) && info[:access_key] != ENV['ACCESS_KEY']
|
|
96
|
+
info.delete(:space)
|
|
97
|
+
client.current_space = nil
|
|
98
|
+
info_changed = true
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
if info[:access_key] != ENV['ACCESS_KEY']
|
|
102
|
+
info[:access_key] = ENV['ACCESS_KEY']
|
|
103
|
+
info_changed = true
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
save_target_info(info, client.target) unless !info_changed
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def check_logged_in
|
|
110
|
+
check_target
|
|
111
|
+
unless client.logged_in?
|
|
112
|
+
if force?
|
|
113
|
+
fail "Please log in with 'jdc login'."
|
|
114
|
+
else
|
|
115
|
+
line c("Please log in first to proceed.", :warning)
|
|
116
|
+
line
|
|
117
|
+
invoke :login
|
|
118
|
+
invalidate_client
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
desc "Help!"
|
|
124
|
+
input :command, :argument => :optional
|
|
125
|
+
def help
|
|
126
|
+
if name = input[:command]
|
|
127
|
+
if cmd = @@commands[name.gsub("-", "_").to_sym]
|
|
128
|
+
Mothership::Help.command_help(cmd)
|
|
129
|
+
else
|
|
130
|
+
unknown_command(name)
|
|
131
|
+
end
|
|
132
|
+
elsif Help.has_groups?
|
|
133
|
+
puts "#{help_header}"
|
|
134
|
+
|
|
135
|
+
Mothership::Help.print_help_groups(@@global, true)
|
|
136
|
+
else
|
|
137
|
+
Mothership::Help.basic_help(@@commands, @@global)
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def help_header
|
|
142
|
+
<<EOS
|
|
143
|
+
Jing Dong Foundry Command Line Interface, version [#{JDC::VERSION}]
|
|
144
|
+
Use 'jdc help [command]' for command details.
|
|
145
|
+
For docs and support visit http://appengine.jd.com/help/jdc.html
|
|
146
|
+
|
|
147
|
+
USAGE EXAMPLES
|
|
148
|
+
$ jdc target api.jd-app.com <-- sets the JDC instance target where your app will be pushed
|
|
149
|
+
$ jdc push <-- deploys app to current app space on current target
|
|
150
|
+
$ jdc target -s staging <-- changes currently targeted app space to 'staging'
|
|
151
|
+
|
|
152
|
+
EOS
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def wrap_errors
|
|
156
|
+
yield
|
|
157
|
+
rescue JFoundry::Timeout => e
|
|
158
|
+
err(e.message)
|
|
159
|
+
rescue Interrupt
|
|
160
|
+
exit_status 130
|
|
161
|
+
rescue Mothership::Error
|
|
162
|
+
raise
|
|
163
|
+
rescue UserError => e
|
|
164
|
+
log_error(e)
|
|
165
|
+
err e.message
|
|
166
|
+
rescue SystemExit
|
|
167
|
+
raise
|
|
168
|
+
rescue UserFriendlyError => e
|
|
169
|
+
err e.message
|
|
170
|
+
=begin
|
|
171
|
+
rescue JFoundry::InvalidAuthToken => e
|
|
172
|
+
line
|
|
173
|
+
line c("Invalid authentication token. Try logging in again with 'cf login'. If problems continue, please contact your Cloud Operator.", :warning)
|
|
174
|
+
rescue JFoundry::Forbidden => e
|
|
175
|
+
if !$cf_asked_auth
|
|
176
|
+
$cf_asked_auth = true
|
|
177
|
+
|
|
178
|
+
line
|
|
179
|
+
line c("Not authenticated! Try logging in:", :warning)
|
|
180
|
+
|
|
181
|
+
# TODO: there's no color here; global flags not being passed
|
|
182
|
+
# through (mothership bug?)
|
|
183
|
+
invoke :login
|
|
184
|
+
|
|
185
|
+
retry
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
log_error(e)
|
|
189
|
+
|
|
190
|
+
err "Denied: #{e.description}"
|
|
191
|
+
=end
|
|
192
|
+
rescue JFoundry::StagingError => e
|
|
193
|
+
message = "Application failed to stage"
|
|
194
|
+
formatted_exception_output(e, message)
|
|
195
|
+
|
|
196
|
+
rescue Exception => e
|
|
197
|
+
formatted_exception_output(e, add_exception_name_to_msg(e))
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def formatted_exception_output(e, msg)
|
|
201
|
+
log_error(e)
|
|
202
|
+
msg << "\ncat #{JDC::CRASH_FILE} # for more details"
|
|
203
|
+
err msg
|
|
204
|
+
|
|
205
|
+
raise if debug?
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def add_exception_name_to_msg(e)
|
|
209
|
+
msg = e.class.name
|
|
210
|
+
msg << ": #{e}" unless e.to_s.empty?
|
|
211
|
+
msg
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def execute(cmd, argv, global = {})
|
|
215
|
+
if input[:help]
|
|
216
|
+
invoke :help, :command => cmd.name.to_s
|
|
217
|
+
else
|
|
218
|
+
wrap_errors do
|
|
219
|
+
@command = cmd
|
|
220
|
+
precondition if respond_to? :precondition
|
|
221
|
+
|
|
222
|
+
save_token_if_it_changes do
|
|
223
|
+
super
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def save_token_if_it_changes
|
|
230
|
+
return yield unless client
|
|
231
|
+
yield
|
|
232
|
+
=begin
|
|
233
|
+
return yield unless client && client.token
|
|
234
|
+
|
|
235
|
+
before_token = client.token
|
|
236
|
+
|
|
237
|
+
yield
|
|
238
|
+
|
|
239
|
+
after_token = client.token
|
|
240
|
+
|
|
241
|
+
return unless after_token
|
|
242
|
+
|
|
243
|
+
if before_token != after_token
|
|
244
|
+
info = target_info
|
|
245
|
+
info[:token] = after_token.auth_header
|
|
246
|
+
save_target_info(info)
|
|
247
|
+
end
|
|
248
|
+
=end
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def log_error(e)
|
|
252
|
+
ensure_config_dir
|
|
253
|
+
|
|
254
|
+
msg = e.class.name
|
|
255
|
+
msg << ": #{e}" unless e.to_s.empty?
|
|
256
|
+
|
|
257
|
+
crash_file = File.expand_path(JDC::CRASH_FILE)
|
|
258
|
+
|
|
259
|
+
FileUtils.mkdir_p(File.dirname(crash_file))
|
|
260
|
+
|
|
261
|
+
File.open(crash_file, "w") do |f|
|
|
262
|
+
f.puts "Time of crash:"
|
|
263
|
+
f.puts " #{Time.now}"
|
|
264
|
+
f.puts ""
|
|
265
|
+
f.puts msg
|
|
266
|
+
f.puts ""
|
|
267
|
+
|
|
268
|
+
if e.respond_to?(:request_trace)
|
|
269
|
+
f.puts "<<<"
|
|
270
|
+
f.puts e.request_trace
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
if e.respond_to?(:response_trace)
|
|
274
|
+
f.puts e.response_trace
|
|
275
|
+
f.puts ">>>"
|
|
276
|
+
f.puts ""
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
jdc_dir = File.expand_path("../../../..", __FILE__) + "/"
|
|
280
|
+
e.backtrace.each do |loc|
|
|
281
|
+
if loc =~ /\/gems\//
|
|
282
|
+
f.puts loc.sub(/.*\/gems\//, "")
|
|
283
|
+
else
|
|
284
|
+
f.puts loc.sub(jdc_dir, "")
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def quiet?
|
|
291
|
+
input[:quiet]
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
def force?
|
|
295
|
+
input[:force]
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def debug?
|
|
299
|
+
!!input[:debug]
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
def color_enabled?
|
|
303
|
+
input[:color]
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
def verbose?
|
|
307
|
+
input[:verbose]
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def user_colors
|
|
311
|
+
return @user_colors if @user_colors
|
|
312
|
+
|
|
313
|
+
colors = File.expand_path(COLORS_FILE)
|
|
314
|
+
|
|
315
|
+
@user_colors = super.dup
|
|
316
|
+
|
|
317
|
+
# most terminal schemes are stupid, so use cyan instead
|
|
318
|
+
@user_colors.each do |k, v|
|
|
319
|
+
if v == :blue
|
|
320
|
+
@user_colors[k] = :cyan
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
if File.exists?(colors)
|
|
325
|
+
YAML.load_file(colors).each do |k, v|
|
|
326
|
+
@user_colors[k.to_sym] = v.to_sym
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
@user_colors
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
def err(msg, status = 1)
|
|
334
|
+
$stderr.puts c(msg, :error)
|
|
335
|
+
exit_status status
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
def fail(msg)
|
|
339
|
+
raise UserError, msg
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
def table(headers, rows)
|
|
343
|
+
tabular(
|
|
344
|
+
!quiet? && headers.collect { |h| h && b(h) },
|
|
345
|
+
*rows)
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
def name_list(xs)
|
|
349
|
+
if xs.empty?
|
|
350
|
+
d("none")
|
|
351
|
+
else
|
|
352
|
+
xs.collect { |x| c(x.name, :name) }.join(", ")
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
def sane_target_url(url)
|
|
357
|
+
unless url =~ /^https?:\/\//
|
|
358
|
+
begin
|
|
359
|
+
TCPSocket.new(url, Net::HTTP.https_default_port)
|
|
360
|
+
url = "https://#{url}"
|
|
361
|
+
rescue Errno::ECONNREFUSED, SocketError, Timeout::Error
|
|
362
|
+
url = "http://#{url}"
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
url.gsub(/\/$/, "")
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
def one_of(*paths)
|
|
370
|
+
paths.each do |p|
|
|
371
|
+
exp = File.expand_path(p)
|
|
372
|
+
return exp if File.exist? exp
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
File.expand_path(paths.first)
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
def client_target
|
|
379
|
+
return File.read(target_file).chomp if File.exists?(target_file)
|
|
380
|
+
sane_target_url(JDC::DEFAULT_API_URL)
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
def ensure_config_dir
|
|
384
|
+
config = File.expand_path(JDC::CONFIG_DIR)
|
|
385
|
+
FileUtils.mkdir_p(config) unless File.exist? config
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
def set_target(url)
|
|
389
|
+
ensure_config_dir
|
|
390
|
+
|
|
391
|
+
File.open(File.expand_path(JDC::TARGET_FILE), "w") do |f|
|
|
392
|
+
f.write(sane_target_url(url))
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
invalidate_client
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
def targets_info
|
|
399
|
+
new_toks = File.expand_path(JDC::TOKENS_FILE)
|
|
400
|
+
|
|
401
|
+
info =
|
|
402
|
+
if File.exist? new_toks
|
|
403
|
+
YAML.load_file(new_toks)
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
info ||= {}
|
|
407
|
+
|
|
408
|
+
normalize_targets_info(info)
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
def normalize_targets_info(info_by_url)
|
|
412
|
+
info_by_url.reduce({}) do |hash, pair|
|
|
413
|
+
key, value = pair
|
|
414
|
+
hash[key] = value.is_a?(String) ? { :token => value } : value
|
|
415
|
+
hash
|
|
416
|
+
end
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
def target_info(target = client_target)
|
|
420
|
+
targets_info[target] || {}
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
def save_targets(ts)
|
|
424
|
+
ensure_config_dir
|
|
425
|
+
|
|
426
|
+
File.open(File.expand_path(JDC::TOKENS_FILE), "w") do |io|
|
|
427
|
+
YAML.dump(ts, io)
|
|
428
|
+
end
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
def save_target_info(info, target = client_target)
|
|
432
|
+
ts = targets_info
|
|
433
|
+
ts[target] = info
|
|
434
|
+
save_targets(ts)
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
def remove_target_info(target = client_target)
|
|
438
|
+
ts = targets_info
|
|
439
|
+
ts.delete target
|
|
440
|
+
save_targets(ts)
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
def invalidate_client
|
|
444
|
+
@@client = nil
|
|
445
|
+
client
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
def client(target = client_target)
|
|
449
|
+
return @@client if defined?(@@client) && @@client
|
|
450
|
+
return unless target
|
|
451
|
+
|
|
452
|
+
info = target_info(target)
|
|
453
|
+
#token = info[:token] && JFoundry::AuthToken.from_hash(info)
|
|
454
|
+
|
|
455
|
+
fail "V1 targets are no longer supported." if info[:version] == 1
|
|
456
|
+
|
|
457
|
+
@@client = build_client(target)
|
|
458
|
+
|
|
459
|
+
@@client.trace = input[:trace]
|
|
460
|
+
|
|
461
|
+
uri = URI.parse(target)
|
|
462
|
+
@@client.log = File.expand_path("#{LOGS_DIR}/#{uri.host}.log")
|
|
463
|
+
|
|
464
|
+
info_changed = false
|
|
465
|
+
unless info.key? :version
|
|
466
|
+
info[:version] = @@client.version
|
|
467
|
+
info_changed = true
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
unless info.key? :access_key
|
|
471
|
+
info[:access_key] = ENV['ACCESS_KEY']
|
|
472
|
+
info_changed = true
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
save_target_info(info, target) unless !info_changed
|
|
476
|
+
|
|
477
|
+
@@client.current_organization = @@client.organization(info[:organization]) if info[:organization]
|
|
478
|
+
@@client.current_space = @@client.space(info[:space]) if info[:space]
|
|
479
|
+
|
|
480
|
+
@@client
|
|
481
|
+
rescue JFoundry::InvalidTarget
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
def build_client(target)
|
|
485
|
+
client = JFoundry::V2::Client.new(target, ENV['ACCESS_KEY'], ENV['SECRET_KEY'], JDC::VERSION)
|
|
486
|
+
client.http_proxy = input[:http_proxy] || ENV['HTTP_PROXY'] || ENV['http_proxy']
|
|
487
|
+
client.https_proxy = input[:https_proxy] || ENV['HTTPS_PROXY'] || ENV['https_proxy']
|
|
488
|
+
client
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
def fail_unknown(display, name)
|
|
492
|
+
fail("Unknown #{display} '#{name}'.")
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
class << self
|
|
496
|
+
def client
|
|
497
|
+
@@client
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
def client=(c)
|
|
501
|
+
@@client = c
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
private
|
|
505
|
+
|
|
506
|
+
def find_by_name(display, &blk)
|
|
507
|
+
proc { |name, *args|
|
|
508
|
+
choices, _ = args
|
|
509
|
+
choices ||= instance_exec(&blk) if block_given?
|
|
510
|
+
|
|
511
|
+
choices.find { |c| c.name == name } ||
|
|
512
|
+
fail_unknown(display, name)
|
|
513
|
+
}
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
def by_name(what, display = what)
|
|
517
|
+
proc { |name, *_|
|
|
518
|
+
client.send(:"#{what}_by_name", name) ||
|
|
519
|
+
fail_unknown(display, name)
|
|
520
|
+
}
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
def find_by_name_insensitive(display, &blk)
|
|
524
|
+
proc { |name, *args|
|
|
525
|
+
choices, _ = args
|
|
526
|
+
choices ||= instance_exec(&blk) if block_given?
|
|
527
|
+
|
|
528
|
+
choices.find { |c| c.name.upcase == name.upcase } ||
|
|
529
|
+
fail_unknown(display, name)
|
|
530
|
+
}
|
|
531
|
+
end
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
private
|
|
535
|
+
|
|
536
|
+
def target_file
|
|
537
|
+
File.expand_path(JDC::TARGET_FILE)
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
def tokens_file
|
|
541
|
+
File.expand_path(JDC::TOKENS_FILE)
|
|
542
|
+
end
|
|
543
|
+
end
|
|
544
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module JDC
|
|
2
|
+
CONFIG_DIR = "~/.jdc".freeze
|
|
3
|
+
|
|
4
|
+
LOGS_DIR = "#{CONFIG_DIR}/logs".freeze
|
|
5
|
+
PLUGINS_FILE = "#{CONFIG_DIR}/plugins.yml".freeze
|
|
6
|
+
TARGET_FILE = "#{CONFIG_DIR}/target".freeze
|
|
7
|
+
TOKENS_FILE = "#{CONFIG_DIR}/tokens.yml".freeze
|
|
8
|
+
COLORS_FILE = "#{CONFIG_DIR}/colors.yml".freeze
|
|
9
|
+
CRASH_FILE = "#{CONFIG_DIR}/crash".freeze
|
|
10
|
+
DEFAULT_API_URL = "api.jd-app.com".freeze
|
|
11
|
+
end
|
data/lib/jdc/errors.rb
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module JDC
|
|
2
|
+
class UserFriendlyError < RuntimeError
|
|
3
|
+
def initialize(msg)
|
|
4
|
+
@message = msg
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def to_s
|
|
8
|
+
@message
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class UserError < UserFriendlyError; end
|
|
13
|
+
|
|
14
|
+
class NotAuthorized < UserError
|
|
15
|
+
def initialize
|
|
16
|
+
@message = "Not authorized."
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
data/lib/jdc/plugin.rb
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require "set"
|
|
2
|
+
require "yaml"
|
|
3
|
+
|
|
4
|
+
require "jdc/constants"
|
|
5
|
+
require "jdc/cli"
|
|
6
|
+
|
|
7
|
+
module JDC
|
|
8
|
+
module Plugin
|
|
9
|
+
@@plugins = []
|
|
10
|
+
|
|
11
|
+
def self.load_all
|
|
12
|
+
# auto-load gems with 'jdc-plugin' in their name
|
|
13
|
+
matching =
|
|
14
|
+
if Gem::Specification.respond_to? :find_all
|
|
15
|
+
Gem::Specification.find_all do |s|
|
|
16
|
+
s.name =~ /jdc-plugin/
|
|
17
|
+
end
|
|
18
|
+
else
|
|
19
|
+
Gem.source_index.find_name(/jdc-plugin/)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
enabled = Set.new(matching.collect(&:name))
|
|
23
|
+
|
|
24
|
+
jdc_gems = Gem.loaded_specs["jdc"]
|
|
25
|
+
((jdc_gems && jdc_gems.dependencies) || Gem.loaded_specs.values).each do |dep|
|
|
26
|
+
if dep.name =~ /jdc-plugin/
|
|
27
|
+
require "#{dep.name}/plugin"
|
|
28
|
+
enabled.delete dep.name
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# allow explicit enabling/disabling of gems via config
|
|
33
|
+
plugins = File.expand_path(JDC::PLUGINS_FILE)
|
|
34
|
+
if File.exists?(plugins) && yaml = YAML.load_file(plugins)
|
|
35
|
+
enabled += yaml["enabled"] if yaml["enabled"]
|
|
36
|
+
enabled -= yaml["disabled"] if yaml["disabled"]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# load up each gem's 'plugin' file
|
|
40
|
+
#
|
|
41
|
+
# we require this file specifically so people can require the gem
|
|
42
|
+
# without it plugging into JDC
|
|
43
|
+
enabled.each do |gemname|
|
|
44
|
+
begin
|
|
45
|
+
require "#{gemname}/plugin"
|
|
46
|
+
rescue Gem::LoadError => e
|
|
47
|
+
puts "Failed to load #{gemname}:"
|
|
48
|
+
puts " #{e}"
|
|
49
|
+
puts
|
|
50
|
+
puts "You may need to update or remove this plugin."
|
|
51
|
+
puts
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|