startapp 0.1.6
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.
- 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
|