startapp 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/COPYRIGHT +1 -0
- data/LICENSE +11 -0
- data/README.md +95 -0
- data/Rakefile +6 -0
- data/autocomplete/rhc_bash +1672 -0
- data/bin/app +37 -0
- data/conf/express.conf +8 -0
- data/features/assets/deploy.tar.gz +0 -0
- data/features/core_feature.rb +191 -0
- data/features/deployments_feature.rb +129 -0
- data/features/domains_feature.rb +58 -0
- data/features/keys_feature.rb +37 -0
- data/features/members_feature.rb +166 -0
- data/lib/rhc/auth/basic.rb +64 -0
- data/lib/rhc/auth/token.rb +102 -0
- data/lib/rhc/auth/token_store.rb +53 -0
- data/lib/rhc/auth.rb +5 -0
- data/lib/rhc/autocomplete.rb +66 -0
- data/lib/rhc/autocomplete_templates/bash.erb +39 -0
- data/lib/rhc/cartridge_helpers.rb +118 -0
- data/lib/rhc/cli.rb +40 -0
- data/lib/rhc/command_runner.rb +185 -0
- data/lib/rhc/commands/account.rb +25 -0
- data/lib/rhc/commands/alias.rb +124 -0
- data/lib/rhc/commands/app.rb +726 -0
- data/lib/rhc/commands/apps.rb +20 -0
- data/lib/rhc/commands/authorization.rb +115 -0
- data/lib/rhc/commands/base.rb +174 -0
- data/lib/rhc/commands/cartridge.rb +329 -0
- data/lib/rhc/commands/clone.rb +66 -0
- data/lib/rhc/commands/configure.rb +20 -0
- data/lib/rhc/commands/create.rb +100 -0
- data/lib/rhc/commands/delete.rb +19 -0
- data/lib/rhc/commands/deploy.rb +32 -0
- data/lib/rhc/commands/deployment.rb +82 -0
- data/lib/rhc/commands/domain.rb +172 -0
- data/lib/rhc/commands/env.rb +142 -0
- data/lib/rhc/commands/force_stop.rb +17 -0
- data/lib/rhc/commands/git_clone.rb +34 -0
- data/lib/rhc/commands/logout.rb +51 -0
- data/lib/rhc/commands/logs.rb +21 -0
- data/lib/rhc/commands/member.rb +148 -0
- data/lib/rhc/commands/port_forward.rb +197 -0
- data/lib/rhc/commands/reload.rb +17 -0
- data/lib/rhc/commands/restart.rb +17 -0
- data/lib/rhc/commands/scp.rb +54 -0
- data/lib/rhc/commands/server.rb +40 -0
- data/lib/rhc/commands/setup.rb +60 -0
- data/lib/rhc/commands/show.rb +43 -0
- data/lib/rhc/commands/snapshot.rb +137 -0
- data/lib/rhc/commands/ssh.rb +51 -0
- data/lib/rhc/commands/sshkey.rb +97 -0
- data/lib/rhc/commands/start.rb +17 -0
- data/lib/rhc/commands/stop.rb +17 -0
- data/lib/rhc/commands/tail.rb +47 -0
- data/lib/rhc/commands/threaddump.rb +14 -0
- data/lib/rhc/commands/tidy.rb +17 -0
- data/lib/rhc/commands.rb +396 -0
- data/lib/rhc/config.rb +321 -0
- data/lib/rhc/context_helper.rb +121 -0
- data/lib/rhc/core_ext.rb +202 -0
- data/lib/rhc/coverage_helper.rb +33 -0
- data/lib/rhc/deployment_helpers.rb +111 -0
- data/lib/rhc/exceptions.rb +256 -0
- data/lib/rhc/git_helpers.rb +106 -0
- data/lib/rhc/help_formatter.rb +55 -0
- data/lib/rhc/helpers.rb +481 -0
- data/lib/rhc/highline_extensions.rb +479 -0
- data/lib/rhc/json.rb +51 -0
- data/lib/rhc/output_helpers.rb +260 -0
- data/lib/rhc/rest/activation.rb +11 -0
- data/lib/rhc/rest/alias.rb +42 -0
- data/lib/rhc/rest/api.rb +87 -0
- data/lib/rhc/rest/application.rb +348 -0
- data/lib/rhc/rest/attributes.rb +36 -0
- data/lib/rhc/rest/authorization.rb +8 -0
- data/lib/rhc/rest/base.rb +79 -0
- data/lib/rhc/rest/cartridge.rb +162 -0
- data/lib/rhc/rest/client.rb +650 -0
- data/lib/rhc/rest/deployment.rb +18 -0
- data/lib/rhc/rest/domain.rb +98 -0
- data/lib/rhc/rest/environment_variable.rb +15 -0
- data/lib/rhc/rest/gear_group.rb +16 -0
- data/lib/rhc/rest/httpclient.rb +145 -0
- data/lib/rhc/rest/key.rb +44 -0
- data/lib/rhc/rest/membership.rb +105 -0
- data/lib/rhc/rest/mock.rb +1042 -0
- data/lib/rhc/rest/user.rb +32 -0
- data/lib/rhc/rest.rb +148 -0
- data/lib/rhc/scp_helpers.rb +27 -0
- data/lib/rhc/ssh_helpers.rb +380 -0
- data/lib/rhc/tar_gz.rb +51 -0
- data/lib/rhc/usage_templates/command_help.erb +51 -0
- data/lib/rhc/usage_templates/command_syntax_help.erb +11 -0
- data/lib/rhc/usage_templates/help.erb +61 -0
- data/lib/rhc/usage_templates/missing_help.erb +1 -0
- data/lib/rhc/usage_templates/options_help.erb +12 -0
- data/lib/rhc/vendor/okjson.rb +600 -0
- data/lib/rhc/vendor/parseconfig.rb +178 -0
- data/lib/rhc/vendor/sshkey.rb +253 -0
- data/lib/rhc/vendor/zliby.rb +628 -0
- data/lib/rhc/version.rb +5 -0
- data/lib/rhc/wizard.rb +637 -0
- data/lib/rhc.rb +34 -0
- data/spec/coverage_helper.rb +82 -0
- data/spec/direct_execution_helper.rb +339 -0
- data/spec/keys/example.pem +23 -0
- data/spec/keys/example_private.pem +27 -0
- data/spec/keys/server.pem +19 -0
- data/spec/rest_spec_helper.rb +31 -0
- data/spec/rhc/assets/cert.crt +22 -0
- data/spec/rhc/assets/cert_key_rsa +27 -0
- data/spec/rhc/assets/empty.txt +0 -0
- data/spec/rhc/assets/env_vars.txt +7 -0
- data/spec/rhc/assets/env_vars_2.txt +1 -0
- data/spec/rhc/assets/foo.txt +1 -0
- data/spec/rhc/assets/targz_corrupted.tar.gz +1 -0
- data/spec/rhc/assets/targz_sample.tar.gz +0 -0
- data/spec/rhc/auth_spec.rb +442 -0
- data/spec/rhc/cli_spec.rb +186 -0
- data/spec/rhc/command_spec.rb +435 -0
- data/spec/rhc/commands/account_spec.rb +42 -0
- data/spec/rhc/commands/alias_spec.rb +333 -0
- data/spec/rhc/commands/app_spec.rb +777 -0
- data/spec/rhc/commands/apps_spec.rb +39 -0
- data/spec/rhc/commands/authorization_spec.rb +157 -0
- data/spec/rhc/commands/cartridge_spec.rb +665 -0
- data/spec/rhc/commands/clone_spec.rb +41 -0
- data/spec/rhc/commands/deployment_spec.rb +327 -0
- data/spec/rhc/commands/domain_spec.rb +401 -0
- data/spec/rhc/commands/env_spec.rb +493 -0
- data/spec/rhc/commands/git_clone_spec.rb +102 -0
- data/spec/rhc/commands/logout_spec.rb +86 -0
- data/spec/rhc/commands/member_spec.rb +247 -0
- data/spec/rhc/commands/port_forward_spec.rb +217 -0
- data/spec/rhc/commands/scp_spec.rb +77 -0
- data/spec/rhc/commands/server_spec.rb +69 -0
- data/spec/rhc/commands/setup_spec.rb +118 -0
- data/spec/rhc/commands/snapshot_spec.rb +179 -0
- data/spec/rhc/commands/ssh_spec.rb +163 -0
- data/spec/rhc/commands/sshkey_spec.rb +188 -0
- data/spec/rhc/commands/tail_spec.rb +81 -0
- data/spec/rhc/commands/threaddump_spec.rb +84 -0
- data/spec/rhc/config_spec.rb +407 -0
- data/spec/rhc/helpers_spec.rb +531 -0
- data/spec/rhc/highline_extensions_spec.rb +314 -0
- data/spec/rhc/json_spec.rb +30 -0
- data/spec/rhc/rest_application_spec.rb +258 -0
- data/spec/rhc/rest_client_spec.rb +752 -0
- data/spec/rhc/rest_spec.rb +740 -0
- data/spec/rhc/targz_spec.rb +55 -0
- data/spec/rhc/wizard_spec.rb +756 -0
- data/spec/spec_helper.rb +575 -0
- data/spec/wizard_spec_helper.rb +330 -0
- metadata +469 -0
data/lib/rhc/commands.rb
ADDED
@@ -0,0 +1,396 @@
|
|
1
|
+
require 'commander'
|
2
|
+
require 'commander/command'
|
3
|
+
|
4
|
+
## monkey patch option parsing to also parse global options all at once
|
5
|
+
# to avoid conflicts and side effects of similar short switches
|
6
|
+
module Commander
|
7
|
+
class Command
|
8
|
+
attr_accessor :default_action, :root, :info
|
9
|
+
def default_action?
|
10
|
+
default_action.present?
|
11
|
+
end
|
12
|
+
def root?
|
13
|
+
root.present?
|
14
|
+
end
|
15
|
+
|
16
|
+
alias_method :option_old, :option
|
17
|
+
def option(*args, &block)
|
18
|
+
opts = args.pop if Hash === args.last
|
19
|
+
option_old(*args, &block).tap do |options|
|
20
|
+
options.last.merge!(opts) if opts
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# Force proxy_option_struct to default to nil for values,
|
26
|
+
# backported for Commander 4.0.3
|
27
|
+
#
|
28
|
+
def proxy_option_struct
|
29
|
+
proxy_options.inject Options.new do |options, (option, value)|
|
30
|
+
# options that are present will evaluate to true
|
31
|
+
value = true if value.nil?
|
32
|
+
# if multiple values were specified for this option, collect it as an
|
33
|
+
# array. on 'fill_arguments' we will decide between stick with the array
|
34
|
+
# (if :type => :list) or just take the last value from array.
|
35
|
+
# not part of the backported method.
|
36
|
+
if proxy_options.select{ |item| item[0] == option }.length > 1
|
37
|
+
if options[option]
|
38
|
+
options[option] << value
|
39
|
+
else
|
40
|
+
options.__send__ :"#{option}=", [value]
|
41
|
+
end
|
42
|
+
else
|
43
|
+
options.__send__ :"#{option}=", value
|
44
|
+
end
|
45
|
+
options
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def deprecated(as_alias=nil)
|
50
|
+
return false unless info
|
51
|
+
return info[:deprecated] if info[:deprecated]
|
52
|
+
return false unless info[:aliases]
|
53
|
+
info[:aliases].select{ |a| ['-',' '].map{ |s| Array(a[:action]).join(s) }.include?(as_alias) }.map{ |a| a[:deprecated] }.first if as_alias
|
54
|
+
end
|
55
|
+
|
56
|
+
def parse_options_and_call_procs *args
|
57
|
+
runner = Commander::Runner.instance
|
58
|
+
opts = OptionParser.new
|
59
|
+
|
60
|
+
# add global options
|
61
|
+
runner.options.each do |option|
|
62
|
+
opts.on(*option[:args], &runner.global_option_proc(option[:switches], &option[:proc]))
|
63
|
+
end
|
64
|
+
|
65
|
+
# add command options
|
66
|
+
@options.each do |option|
|
67
|
+
opts.on(*option[:args], &option[:proc])
|
68
|
+
opts
|
69
|
+
end
|
70
|
+
|
71
|
+
# Separate option lists with '--'
|
72
|
+
remaining = args.split('--').map{ |a| opts.parse!(a) }.inject([]) do |arr, h|
|
73
|
+
arr << '--'
|
74
|
+
arr.concat(h)
|
75
|
+
end
|
76
|
+
remaining.shift
|
77
|
+
|
78
|
+
_, config_path = proxy_options.find{ |arg| arg[0] == :config }
|
79
|
+
clean, _ = proxy_options.find{ |arg| arg[0] == :clean }
|
80
|
+
|
81
|
+
begin
|
82
|
+
@config = RHC::Config.new
|
83
|
+
@config.use_config(config_path) if config_path
|
84
|
+
$terminal.debug("Using config file #{@config.config_path}")
|
85
|
+
|
86
|
+
unless clean
|
87
|
+
@config.to_options.each_pair do |key, value|
|
88
|
+
next if proxy_options.detect{ |arr| arr[0] == key }
|
89
|
+
if sw = opts.send(:search, :long, key.to_s.gsub(/_/, '-'))
|
90
|
+
_, cb, val = sw.send(:conv_arg, nil, value) {|*exc| raise(*exc) }
|
91
|
+
cb.call(val) if cb
|
92
|
+
else
|
93
|
+
proxy_options << [key, value]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
rescue ArgumentError => e
|
98
|
+
n = OptionParser::InvalidOption.new(e.message)
|
99
|
+
n.reason = "The configuration file #{@config.path} contains an invalid setting"
|
100
|
+
n.set_backtrace(e.backtrace)
|
101
|
+
raise n
|
102
|
+
rescue OptionParser::ParseError => e
|
103
|
+
e.reason = "The configuration file #{@config.path} contains an invalid setting"
|
104
|
+
raise
|
105
|
+
end
|
106
|
+
remaining
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
#
|
112
|
+
# Allow Command::Options to lazily evaluate procs and lambdas
|
113
|
+
#
|
114
|
+
module Commander
|
115
|
+
class Command
|
116
|
+
remove_const(:Options)
|
117
|
+
class Options
|
118
|
+
def initialize(init=nil)
|
119
|
+
@defaults = {}
|
120
|
+
@table = {}
|
121
|
+
default(init) if init
|
122
|
+
end
|
123
|
+
def respond_to?(meth)
|
124
|
+
super || meth.to_s =~ /^\w+(=)?$/
|
125
|
+
end
|
126
|
+
def method_missing meth, *args, &block
|
127
|
+
if meth.to_s =~ /^\w+=$/
|
128
|
+
raise ArgumentError, "Options does not support #{meth} without a single argument" if args.length != 1
|
129
|
+
self[meth.to_s.chop] = args.first
|
130
|
+
elsif meth.to_s =~ /^\w+$/
|
131
|
+
if !@table.has_key?(meth) && !@defaults.has_key?(meth)
|
132
|
+
begin; return super; rescue NoMethodError; nil; end
|
133
|
+
end
|
134
|
+
raise ArgumentError, "Options does not support #{meth} with arguments" if args.length != 0
|
135
|
+
self[meth]
|
136
|
+
else
|
137
|
+
super
|
138
|
+
end
|
139
|
+
end
|
140
|
+
def respond_to_missing?(meth, private_method = false)
|
141
|
+
meth.to_s =~ /^\w+(=)?$/
|
142
|
+
end
|
143
|
+
def []=(meth, value)
|
144
|
+
@table[meth.to_sym] = value
|
145
|
+
end
|
146
|
+
def [](meth)
|
147
|
+
k = meth.to_sym
|
148
|
+
value = @table.has_key?(k) ? @table[k] : @defaults[k]
|
149
|
+
value = value.call if value.is_a? Proc
|
150
|
+
value
|
151
|
+
end
|
152
|
+
def __explicit__
|
153
|
+
@table
|
154
|
+
end
|
155
|
+
def ==(other)
|
156
|
+
@table == other.instance_variable_get(:@table)
|
157
|
+
end
|
158
|
+
def default defaults = {}
|
159
|
+
@defaults.merge!(__to_hash__(defaults))
|
160
|
+
end
|
161
|
+
def __replace__(options)
|
162
|
+
@table = __to_hash__(options)
|
163
|
+
end
|
164
|
+
def __hash__
|
165
|
+
@defaults.merge(@table)
|
166
|
+
end
|
167
|
+
def __to_hash__(obj)
|
168
|
+
Options === obj ? obj.__hash__ : obj
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
module RHC
|
175
|
+
module Commands
|
176
|
+
autoload :Base, 'rhc/commands/base'
|
177
|
+
|
178
|
+
def self.load
|
179
|
+
Dir[File.join(File.dirname(__FILE__), "commands", "*.rb")].each do |file|
|
180
|
+
require file
|
181
|
+
end
|
182
|
+
self
|
183
|
+
end
|
184
|
+
def self.add(opts)
|
185
|
+
commands[opts[:name]] = opts
|
186
|
+
end
|
187
|
+
def self.global_option(*args, &block)
|
188
|
+
global_options << [args.freeze, block]
|
189
|
+
end
|
190
|
+
|
191
|
+
def self.deprecated!
|
192
|
+
instance = Commander::Runner.instance
|
193
|
+
command_name = instance.command_name_from_args
|
194
|
+
command = instance.active_command
|
195
|
+
|
196
|
+
if new_cmd = command.deprecated(command_name)
|
197
|
+
new_cmd = "app #{command.name}" if new_cmd == true
|
198
|
+
RHC::Helpers.deprecated_command new_cmd
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def self.needs_configuration!(cmd, options, config)
|
203
|
+
if not (cmd.class.suppress_wizard? or
|
204
|
+
options.noprompt or
|
205
|
+
options.help or
|
206
|
+
config.has_local_config? or
|
207
|
+
config.has_opts_config?)
|
208
|
+
|
209
|
+
$stderr.puts RHC::Helpers.color("You have not yet configured the StartApp client tools. Please run 'app setup'.", :yellow)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def self.to_commander(instance=Commander::Runner.instance)
|
214
|
+
global_options.each do |args, block|
|
215
|
+
args = args.dup
|
216
|
+
opts = (args.pop if Hash === args.last) || {}
|
217
|
+
option = instance.global_option(*args, &block).last
|
218
|
+
option.merge!(opts)
|
219
|
+
end
|
220
|
+
commands.each_pair do |name, opts|
|
221
|
+
name = Array(name)
|
222
|
+
names = [name.reverse.join('-'), name.join(' ')] if name.length > 1
|
223
|
+
name = name.join('-')
|
224
|
+
|
225
|
+
instance.command name do |c|
|
226
|
+
c.description = opts[:description]
|
227
|
+
c.summary = opts[:summary]
|
228
|
+
c.syntax = opts[:syntax]
|
229
|
+
c.default_action = opts[:default]
|
230
|
+
|
231
|
+
c.info = opts
|
232
|
+
|
233
|
+
(options_metadata = Array(opts[:options])).each do |o|
|
234
|
+
option_data = [o[:switches], o[:type], o[:description], o.slice(:optional, :default, :hide, :covered_by)].compact.flatten(1)
|
235
|
+
c.option *option_data
|
236
|
+
o[:arg] = Commander::Runner.switch_to_sym(Array(o[:switches]).last)
|
237
|
+
end
|
238
|
+
|
239
|
+
(args_metadata = Array(opts[:args])).each do |meta|
|
240
|
+
switches = meta[:switches]
|
241
|
+
unless switches.blank?
|
242
|
+
switches = switches.dup
|
243
|
+
switches << meta[:description]
|
244
|
+
switches << meta.slice(:optional, :default, :hide, :covered_by, :allow_nil)
|
245
|
+
c.option *switches
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
Array(opts[:aliases]).each do |a|
|
250
|
+
action = Array(a[:action])
|
251
|
+
[' ', '-'].each do |s|
|
252
|
+
cmd = action.join(s)
|
253
|
+
instance.alias_command cmd, name
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
if names
|
258
|
+
names.each{ |alt| instance.alias_command alt, name }
|
259
|
+
else
|
260
|
+
c.root = true
|
261
|
+
end
|
262
|
+
|
263
|
+
c.when_called do |args, options|
|
264
|
+
deprecated!
|
265
|
+
|
266
|
+
config = c.instance_variable_get(:@config)
|
267
|
+
|
268
|
+
cmd = opts[:class].new
|
269
|
+
cmd.options = options
|
270
|
+
cmd.config = config
|
271
|
+
|
272
|
+
args = fill_arguments(cmd, options, args_metadata, options_metadata, args)
|
273
|
+
needs_configuration!(cmd, options, config)
|
274
|
+
|
275
|
+
return execute(cmd, :help, args) unless opts[:method]
|
276
|
+
execute(cmd, opts[:method], args)
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
self
|
281
|
+
end
|
282
|
+
|
283
|
+
protected
|
284
|
+
def self.execute(cmd, method, args)
|
285
|
+
cmd.send(method, *args)
|
286
|
+
end
|
287
|
+
|
288
|
+
def self.fill_arguments(cmd, options, args, opts, arguments)
|
289
|
+
# process defaults
|
290
|
+
defaults = {}
|
291
|
+
covers = {}
|
292
|
+
(opts + args).each do |option_meta|
|
293
|
+
arg = option_meta[:option_symbol] || option_meta[:name] || option_meta[:arg] or next
|
294
|
+
if arg && option_meta[:type] != :list && options[arg].is_a?(Array)
|
295
|
+
options[arg] = options[arg].last
|
296
|
+
end
|
297
|
+
Array(option_meta[:covered_by]).each{ |sym| (covers[sym] ||= []) << arg }
|
298
|
+
|
299
|
+
case v = option_meta[:default]
|
300
|
+
when Symbol
|
301
|
+
cmd.send(v, defaults, arg)
|
302
|
+
when Proc
|
303
|
+
v.call(defaults, arg)
|
304
|
+
when nil
|
305
|
+
else
|
306
|
+
defaults[arg] = v
|
307
|
+
end
|
308
|
+
end
|
309
|
+
options.default(defaults)
|
310
|
+
|
311
|
+
# process required options
|
312
|
+
opts.each do |option_meta|
|
313
|
+
raise ArgumentError.new("Missing required option '#{option_meta[:arg]}'.") if option_meta[:required] && options[option_meta[:arg]].nil?
|
314
|
+
end
|
315
|
+
|
316
|
+
slots = Array.new(args.count)
|
317
|
+
available = arguments.dup
|
318
|
+
|
319
|
+
args.each_with_index do |arg, i|
|
320
|
+
value = argument_to_slot(options, available, arg)
|
321
|
+
|
322
|
+
if value.nil?
|
323
|
+
if arg[:allow_nil] != true && !arg[:optional]
|
324
|
+
raise ArgumentError, "Missing required argument '#{arg[:name]}'."
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
slots[i] = value
|
329
|
+
end
|
330
|
+
|
331
|
+
raise ArgumentError, "Too many arguments passed in: #{available.reverse.join(" ")}" unless available.empty?
|
332
|
+
|
333
|
+
# reset covered arguments
|
334
|
+
options.__explicit__.keys.each do |k|
|
335
|
+
if covered = covers[k]
|
336
|
+
covered.each do |sym|
|
337
|
+
raise ArgumentError, "The options '#{sym}' and '#{k}' cannot both be provided" unless options.__explicit__[sym].nil?
|
338
|
+
options[sym] = nil
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
slots
|
344
|
+
end
|
345
|
+
|
346
|
+
def self.argument_to_slot(options, available, arg)
|
347
|
+
if Array(arg[:covered_by]).any?{ |k| !options.__explicit__[k].nil? }
|
348
|
+
return nil
|
349
|
+
end
|
350
|
+
|
351
|
+
option = arg[:option_symbol]
|
352
|
+
value = options.__explicit__[option] if option
|
353
|
+
if value.nil?
|
354
|
+
value =
|
355
|
+
if arg[:type] == :list
|
356
|
+
take_leading_list(available)
|
357
|
+
else
|
358
|
+
v = available.shift
|
359
|
+
if v == '--'
|
360
|
+
v = nil
|
361
|
+
else
|
362
|
+
available.shift if available.first == '--'
|
363
|
+
end
|
364
|
+
v
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
value = options[option] if option && (value.nil? || (value.is_a?(Array) && value.blank?))
|
369
|
+
if arg[:type] == :list
|
370
|
+
value = Array(value)
|
371
|
+
end
|
372
|
+
options[option] = value if option && !value.nil?
|
373
|
+
|
374
|
+
value
|
375
|
+
end
|
376
|
+
|
377
|
+
def self.take_leading_list(available)
|
378
|
+
if i = available.index('--')
|
379
|
+
left = available.shift(i)
|
380
|
+
available.shift
|
381
|
+
left
|
382
|
+
else
|
383
|
+
left = available.dup
|
384
|
+
available.clear
|
385
|
+
left
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
def self.commands
|
390
|
+
@commands ||= {}
|
391
|
+
end
|
392
|
+
def self.global_options
|
393
|
+
@options ||= []
|
394
|
+
end
|
395
|
+
end
|
396
|
+
end
|
data/lib/rhc/config.rb
ADDED
@@ -0,0 +1,321 @@
|
|
1
|
+
require 'rhc/vendor/parseconfig'
|
2
|
+
require 'rhc/core_ext'
|
3
|
+
|
4
|
+
module RHC
|
5
|
+
|
6
|
+
module ConfigEnv
|
7
|
+
def conf_name
|
8
|
+
"#{ENV['OPENSHIFT_CONFIG'].presence || 'express'}.conf"
|
9
|
+
end
|
10
|
+
def home_conf_dir
|
11
|
+
File.join(home_dir, '.startapp')
|
12
|
+
end
|
13
|
+
def local_config_path
|
14
|
+
File.join(home_conf_dir, conf_name)
|
15
|
+
end
|
16
|
+
def ssh_dir
|
17
|
+
File.join(home_dir, '.ssh')
|
18
|
+
end
|
19
|
+
def ssh_priv_key_file_path
|
20
|
+
File.join(ssh_dir, 'id_rsa')
|
21
|
+
end
|
22
|
+
def ssh_pub_key_file_path
|
23
|
+
File.join(ssh_dir, 'id_rsa.pub')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
# Responsible for encapsulating the loading and retrieval of OpenShift
|
29
|
+
# configuration files and converting them to commandline option
|
30
|
+
# equivalents. It also provides the converse option - converting a set
|
31
|
+
# of commandline options back into a config file.
|
32
|
+
#
|
33
|
+
# In general, the values stored in the config should be identical (require
|
34
|
+
# little or no type conversion) to their option form. As new global
|
35
|
+
# options are added, only this class should have to change to persist that
|
36
|
+
# option.
|
37
|
+
#
|
38
|
+
# During normal use, a new Config object should load the appropriate
|
39
|
+
# settings and those settings should be converted into commandline option
|
40
|
+
# defaults.
|
41
|
+
#
|
42
|
+
# TODO: Encapsulate config writing to the home location
|
43
|
+
# TODO: Allow the config object to initialized with a path
|
44
|
+
# TODO: Remove deprecated methods, remove extra sources.
|
45
|
+
#
|
46
|
+
class Config
|
47
|
+
include ConfigEnv
|
48
|
+
|
49
|
+
# Option name [config_key type comment_string_for_config]
|
50
|
+
# if nil, == key nil == string won't be written to file if nil
|
51
|
+
OPTIONS = {
|
52
|
+
:server => ['libra_server', nil, 'The StartApp server to connect to'],
|
53
|
+
:rhlogin => ['default_rhlogin', nil, 'Your StartApp login name'],
|
54
|
+
:password => nil,
|
55
|
+
:use_authorization_tokens =>
|
56
|
+
[nil, :boolean, 'If true, the server will attempt to create and use authorization tokens to connect to the server'],
|
57
|
+
:timeout => [nil, :integer, 'The default timeout for network operations'],
|
58
|
+
:insecure => [nil, :boolean, "If true, certificate errors will be ignored.\nWARNING: This may allow others to eavesdrop on your communication with OpenShift."],
|
59
|
+
:ssl_version => [nil, nil, 'The SSL protocol version to use when connecting to this server'],
|
60
|
+
:ssl_client_cert_file => [nil, :path_to_file, 'A client certificate file for use with your server'],
|
61
|
+
:ssl_ca_file => [nil, :path_to_file, 'A file containing CA one or more certificates'],
|
62
|
+
}
|
63
|
+
|
64
|
+
def self.options_to_config(options)
|
65
|
+
OPTIONS.inject([]) do |arr, (name, opts)|
|
66
|
+
opts ||= []
|
67
|
+
next arr unless opts[2]
|
68
|
+
value = options[name]
|
69
|
+
arr.concat(opts[2].each_line.to_a.map(&:strip).map{ |s| "# #{s}" })
|
70
|
+
arr << "#{value.nil? ? '#' : ''}#{opts[0] || name}=#{self.type_to_config(opts[1], value)}"
|
71
|
+
arr << ""
|
72
|
+
arr
|
73
|
+
end.join("\n")
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.type_to_config(type, value)
|
77
|
+
case type
|
78
|
+
when :integer, :boolean
|
79
|
+
value.nil? ? "<#{type}>" : value
|
80
|
+
else
|
81
|
+
value.nil? ? "<#{type || 'string'}>" : value
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# DEPRECATED - will be removed when old commands are gone
|
86
|
+
def self.default
|
87
|
+
@default ||= RHC::Config.new
|
88
|
+
end
|
89
|
+
|
90
|
+
# DEPRECATED - will be removed when old commands are gone
|
91
|
+
def self.method_missing(method, *args, &block)
|
92
|
+
if default.respond_to?(method)
|
93
|
+
default.send(method, *args, &block)
|
94
|
+
else
|
95
|
+
raise NoMethodError, method
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# DEPRECATED - will be removed when old commands are gone
|
100
|
+
def self.initialize
|
101
|
+
@default = nil
|
102
|
+
default
|
103
|
+
end
|
104
|
+
|
105
|
+
# DEPRECATED - will be removed when old commands are gone
|
106
|
+
def initialize
|
107
|
+
set_defaults
|
108
|
+
end
|
109
|
+
|
110
|
+
# DEPRECATED - will be removed when old commands are gone
|
111
|
+
def read_config_files
|
112
|
+
load_config_files
|
113
|
+
end
|
114
|
+
|
115
|
+
# DEPRECATED - will be removed when old commands are gone
|
116
|
+
def set_defaults
|
117
|
+
@defaults = RHC::Vendor::ParseConfig.new()
|
118
|
+
@opts = RHC::Vendor::ParseConfig.new() # option switches that override config file
|
119
|
+
|
120
|
+
@env_config = RHC::Vendor::ParseConfig.new()
|
121
|
+
@global_config = nil
|
122
|
+
@local_config = nil
|
123
|
+
@opts_config = nil # config file passed in the options
|
124
|
+
|
125
|
+
@default_proxy = nil
|
126
|
+
|
127
|
+
@defaults.add('libra_server', 'broker.startapp.bg')
|
128
|
+
@env_config.add('libra_server', ENV['LIBRA_SERVER']) if ENV['LIBRA_SERVER']
|
129
|
+
@env_config.add('libra_server', ENV['RHC_SERVER']) if ENV['RHC_SERVER']
|
130
|
+
|
131
|
+
@opts_config_path = nil
|
132
|
+
end
|
133
|
+
|
134
|
+
def to_options
|
135
|
+
OPTIONS.inject({}) do |h, (name, opts)|
|
136
|
+
opts = Array(opts)
|
137
|
+
value = self[opts[0] || name.to_s]
|
138
|
+
if value
|
139
|
+
value = case opts[1]
|
140
|
+
when :integer
|
141
|
+
Integer(value)
|
142
|
+
when :boolean
|
143
|
+
!!(value =~ /^\s*(y|yes|1|t|true)\s*$/i)
|
144
|
+
else
|
145
|
+
value unless value.blank?
|
146
|
+
end
|
147
|
+
h[name] = value unless value.nil?
|
148
|
+
end
|
149
|
+
h
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def save!(options)
|
154
|
+
File.open(path, 'w'){ |f| f.puts self.class.options_to_config(options) }
|
155
|
+
@opts, @opts_config, @local_config, @global_config = nil
|
156
|
+
load_config_files
|
157
|
+
self
|
158
|
+
end
|
159
|
+
|
160
|
+
def [](key)
|
161
|
+
lazy_init
|
162
|
+
|
163
|
+
# evaluate in cascading order
|
164
|
+
configs = [@opts, @opts_config, @env_config, @local_config, @global_config, @defaults]
|
165
|
+
result = nil
|
166
|
+
configs.each do |conf|
|
167
|
+
result = conf[key] if !conf.nil?
|
168
|
+
break if !result.nil?
|
169
|
+
end
|
170
|
+
|
171
|
+
result
|
172
|
+
end
|
173
|
+
|
174
|
+
# DEPRECATED - will be removed when old commands are gone
|
175
|
+
def get_value(key)
|
176
|
+
self[key]
|
177
|
+
end
|
178
|
+
|
179
|
+
# DEPRECATED - underlying value and command option needs to be migrated to login
|
180
|
+
def username
|
181
|
+
self['default_rhlogin']
|
182
|
+
end
|
183
|
+
|
184
|
+
# DEPRECATED - will be removed when old commands are gone
|
185
|
+
def set_local_config(conf_path, must_exist=true)
|
186
|
+
conf_path = File.expand_path(conf_path)
|
187
|
+
@config_path = conf_path if @opts_config_path.nil?
|
188
|
+
@local_config = RHC::Vendor::ParseConfig.new(conf_path)
|
189
|
+
rescue Errno::EACCES => e
|
190
|
+
raise Errno::EACCES.new "Could not open config file: #{e.message}" if must_exist
|
191
|
+
end
|
192
|
+
|
193
|
+
# DEPRECATED - needs to be renamed to something cleaner
|
194
|
+
def set_opts_config(conf_path)
|
195
|
+
@opts_config_path = File.expand_path(conf_path)
|
196
|
+
@config_path = @opts_config_path
|
197
|
+
@opts_config = RHC::Vendor::ParseConfig.new(@opts_config_path) if File.exists?(@opts_config_path)
|
198
|
+
rescue Errno::EACCES => e
|
199
|
+
raise Errno::EACCES.new "Could not open config file: #{e.message}"
|
200
|
+
end
|
201
|
+
|
202
|
+
def use_config(path)
|
203
|
+
path = File.expand_path(path)
|
204
|
+
set_opts_config(path)
|
205
|
+
rescue => e
|
206
|
+
raise ArgumentError, "Unable to read configuration file: #{e.message}", $!.backtrace
|
207
|
+
end
|
208
|
+
|
209
|
+
# DEPRECATED - will be removed when old commands are gone
|
210
|
+
def check_cpath(opts)
|
211
|
+
unless opts["config"].nil?
|
212
|
+
opts_config_path = File.expand_path(opts["config"])
|
213
|
+
if !File.readable?(opts_config_path)
|
214
|
+
raise Errno::EACCES.new "Could not open config file: #{@opts_config_path}"
|
215
|
+
else
|
216
|
+
set_opts_config(opts_config_path)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
# DEPRECATED - may be made private
|
222
|
+
def global_config_path
|
223
|
+
linux_cfg = '/etc/openshift/' + conf_name
|
224
|
+
File.exists?(linux_cfg) ? linux_cfg : File.join(File.expand_path(File.dirname(__FILE__) + "/../../conf"), conf_name)
|
225
|
+
end
|
226
|
+
|
227
|
+
def has_global_config?
|
228
|
+
lazy_init
|
229
|
+
!@global_config.nil?
|
230
|
+
end
|
231
|
+
|
232
|
+
def has_local_config?
|
233
|
+
lazy_init
|
234
|
+
!@local_config.nil?
|
235
|
+
end
|
236
|
+
|
237
|
+
def has_opts_config?
|
238
|
+
!@opts_config.nil?
|
239
|
+
end
|
240
|
+
|
241
|
+
# DEPRECATED - should be moved to Helpers
|
242
|
+
def should_run_ssh_wizard?
|
243
|
+
not File.exists? ssh_priv_key_file_path
|
244
|
+
end
|
245
|
+
|
246
|
+
##
|
247
|
+
# config_path
|
248
|
+
#
|
249
|
+
# authoritive configuration path
|
250
|
+
# this is used to determine where config options should be written to
|
251
|
+
# when a script modifies the config such as in rhc setup
|
252
|
+
def config_path
|
253
|
+
@config_path ||= local_config_path
|
254
|
+
end
|
255
|
+
def path
|
256
|
+
config_path
|
257
|
+
end
|
258
|
+
|
259
|
+
def home_dir
|
260
|
+
RHC::Config.home_dir
|
261
|
+
end
|
262
|
+
|
263
|
+
def home_conf_path
|
264
|
+
home_conf_dir
|
265
|
+
end
|
266
|
+
|
267
|
+
# DEPRECATED - will be removed when old commands are gone
|
268
|
+
def default_rhlogin
|
269
|
+
get_value('default_rhlogin')
|
270
|
+
end
|
271
|
+
|
272
|
+
# DEPRECATED - will be removed when old commands are gone
|
273
|
+
def default_proxy
|
274
|
+
@default_proxy ||= (
|
275
|
+
proxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
|
276
|
+
if proxy
|
277
|
+
if proxy !~ /^(\w+):\/\// then
|
278
|
+
proxy = "http://#{proxy}"
|
279
|
+
end
|
280
|
+
ENV['http_proxy'] = proxy
|
281
|
+
proxy_uri = URI.parse(ENV['http_proxy'])
|
282
|
+
Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password)
|
283
|
+
else
|
284
|
+
Net::HTTP
|
285
|
+
end
|
286
|
+
)
|
287
|
+
end
|
288
|
+
|
289
|
+
# DEPRECATED - will be removed when old commands are gone
|
290
|
+
def using_proxy?
|
291
|
+
default_proxy.instance_variable_get(:@is_proxy_class) || false
|
292
|
+
end
|
293
|
+
|
294
|
+
# DEPRECATED - will be removed when old commands are gone
|
295
|
+
def proxy_vars
|
296
|
+
Hash[[:address,:user,:pass,:port].map do |x|
|
297
|
+
[x,default_proxy.instance_variable_get("@proxy_#{x}")]
|
298
|
+
end]
|
299
|
+
end
|
300
|
+
|
301
|
+
private
|
302
|
+
# Allow mocking of the home dir
|
303
|
+
def self.home_dir
|
304
|
+
File.expand_path('~')
|
305
|
+
end
|
306
|
+
|
307
|
+
def load_config_files
|
308
|
+
@global_config = RHC::Vendor::ParseConfig.new(global_config_path) if File.exists?(global_config_path)
|
309
|
+
@local_config = RHC::Vendor::ParseConfig.new(File.expand_path(local_config_path)) if File.exists?(local_config_path)
|
310
|
+
rescue Errno::EACCES => e
|
311
|
+
raise Errno::EACCES.new("Could not open config file: #{e.message}")
|
312
|
+
end
|
313
|
+
|
314
|
+
def lazy_init
|
315
|
+
unless @loaded
|
316
|
+
load_config_files
|
317
|
+
@loaded = true
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|