startapp 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (156) hide show
  1. checksums.yaml +7 -0
  2. data/COPYRIGHT +1 -0
  3. data/LICENSE +11 -0
  4. data/README.md +95 -0
  5. data/Rakefile +6 -0
  6. data/autocomplete/rhc_bash +1672 -0
  7. data/bin/app +37 -0
  8. data/conf/express.conf +8 -0
  9. data/features/assets/deploy.tar.gz +0 -0
  10. data/features/core_feature.rb +191 -0
  11. data/features/deployments_feature.rb +129 -0
  12. data/features/domains_feature.rb +58 -0
  13. data/features/keys_feature.rb +37 -0
  14. data/features/members_feature.rb +166 -0
  15. data/lib/rhc/auth/basic.rb +64 -0
  16. data/lib/rhc/auth/token.rb +102 -0
  17. data/lib/rhc/auth/token_store.rb +53 -0
  18. data/lib/rhc/auth.rb +5 -0
  19. data/lib/rhc/autocomplete.rb +66 -0
  20. data/lib/rhc/autocomplete_templates/bash.erb +39 -0
  21. data/lib/rhc/cartridge_helpers.rb +118 -0
  22. data/lib/rhc/cli.rb +40 -0
  23. data/lib/rhc/command_runner.rb +185 -0
  24. data/lib/rhc/commands/account.rb +25 -0
  25. data/lib/rhc/commands/alias.rb +124 -0
  26. data/lib/rhc/commands/app.rb +726 -0
  27. data/lib/rhc/commands/apps.rb +20 -0
  28. data/lib/rhc/commands/authorization.rb +115 -0
  29. data/lib/rhc/commands/base.rb +174 -0
  30. data/lib/rhc/commands/cartridge.rb +329 -0
  31. data/lib/rhc/commands/clone.rb +66 -0
  32. data/lib/rhc/commands/configure.rb +20 -0
  33. data/lib/rhc/commands/create.rb +100 -0
  34. data/lib/rhc/commands/delete.rb +19 -0
  35. data/lib/rhc/commands/deploy.rb +32 -0
  36. data/lib/rhc/commands/deployment.rb +82 -0
  37. data/lib/rhc/commands/domain.rb +172 -0
  38. data/lib/rhc/commands/env.rb +142 -0
  39. data/lib/rhc/commands/force_stop.rb +17 -0
  40. data/lib/rhc/commands/git_clone.rb +34 -0
  41. data/lib/rhc/commands/logout.rb +51 -0
  42. data/lib/rhc/commands/logs.rb +21 -0
  43. data/lib/rhc/commands/member.rb +148 -0
  44. data/lib/rhc/commands/port_forward.rb +197 -0
  45. data/lib/rhc/commands/reload.rb +17 -0
  46. data/lib/rhc/commands/restart.rb +17 -0
  47. data/lib/rhc/commands/scp.rb +54 -0
  48. data/lib/rhc/commands/server.rb +40 -0
  49. data/lib/rhc/commands/setup.rb +60 -0
  50. data/lib/rhc/commands/show.rb +43 -0
  51. data/lib/rhc/commands/snapshot.rb +137 -0
  52. data/lib/rhc/commands/ssh.rb +51 -0
  53. data/lib/rhc/commands/sshkey.rb +97 -0
  54. data/lib/rhc/commands/start.rb +17 -0
  55. data/lib/rhc/commands/stop.rb +17 -0
  56. data/lib/rhc/commands/tail.rb +47 -0
  57. data/lib/rhc/commands/threaddump.rb +14 -0
  58. data/lib/rhc/commands/tidy.rb +17 -0
  59. data/lib/rhc/commands.rb +396 -0
  60. data/lib/rhc/config.rb +321 -0
  61. data/lib/rhc/context_helper.rb +121 -0
  62. data/lib/rhc/core_ext.rb +202 -0
  63. data/lib/rhc/coverage_helper.rb +33 -0
  64. data/lib/rhc/deployment_helpers.rb +111 -0
  65. data/lib/rhc/exceptions.rb +256 -0
  66. data/lib/rhc/git_helpers.rb +106 -0
  67. data/lib/rhc/help_formatter.rb +55 -0
  68. data/lib/rhc/helpers.rb +481 -0
  69. data/lib/rhc/highline_extensions.rb +479 -0
  70. data/lib/rhc/json.rb +51 -0
  71. data/lib/rhc/output_helpers.rb +260 -0
  72. data/lib/rhc/rest/activation.rb +11 -0
  73. data/lib/rhc/rest/alias.rb +42 -0
  74. data/lib/rhc/rest/api.rb +87 -0
  75. data/lib/rhc/rest/application.rb +348 -0
  76. data/lib/rhc/rest/attributes.rb +36 -0
  77. data/lib/rhc/rest/authorization.rb +8 -0
  78. data/lib/rhc/rest/base.rb +79 -0
  79. data/lib/rhc/rest/cartridge.rb +162 -0
  80. data/lib/rhc/rest/client.rb +650 -0
  81. data/lib/rhc/rest/deployment.rb +18 -0
  82. data/lib/rhc/rest/domain.rb +98 -0
  83. data/lib/rhc/rest/environment_variable.rb +15 -0
  84. data/lib/rhc/rest/gear_group.rb +16 -0
  85. data/lib/rhc/rest/httpclient.rb +145 -0
  86. data/lib/rhc/rest/key.rb +44 -0
  87. data/lib/rhc/rest/membership.rb +105 -0
  88. data/lib/rhc/rest/mock.rb +1042 -0
  89. data/lib/rhc/rest/user.rb +32 -0
  90. data/lib/rhc/rest.rb +148 -0
  91. data/lib/rhc/scp_helpers.rb +27 -0
  92. data/lib/rhc/ssh_helpers.rb +380 -0
  93. data/lib/rhc/tar_gz.rb +51 -0
  94. data/lib/rhc/usage_templates/command_help.erb +51 -0
  95. data/lib/rhc/usage_templates/command_syntax_help.erb +11 -0
  96. data/lib/rhc/usage_templates/help.erb +61 -0
  97. data/lib/rhc/usage_templates/missing_help.erb +1 -0
  98. data/lib/rhc/usage_templates/options_help.erb +12 -0
  99. data/lib/rhc/vendor/okjson.rb +600 -0
  100. data/lib/rhc/vendor/parseconfig.rb +178 -0
  101. data/lib/rhc/vendor/sshkey.rb +253 -0
  102. data/lib/rhc/vendor/zliby.rb +628 -0
  103. data/lib/rhc/version.rb +5 -0
  104. data/lib/rhc/wizard.rb +637 -0
  105. data/lib/rhc.rb +34 -0
  106. data/spec/coverage_helper.rb +82 -0
  107. data/spec/direct_execution_helper.rb +339 -0
  108. data/spec/keys/example.pem +23 -0
  109. data/spec/keys/example_private.pem +27 -0
  110. data/spec/keys/server.pem +19 -0
  111. data/spec/rest_spec_helper.rb +31 -0
  112. data/spec/rhc/assets/cert.crt +22 -0
  113. data/spec/rhc/assets/cert_key_rsa +27 -0
  114. data/spec/rhc/assets/empty.txt +0 -0
  115. data/spec/rhc/assets/env_vars.txt +7 -0
  116. data/spec/rhc/assets/env_vars_2.txt +1 -0
  117. data/spec/rhc/assets/foo.txt +1 -0
  118. data/spec/rhc/assets/targz_corrupted.tar.gz +1 -0
  119. data/spec/rhc/assets/targz_sample.tar.gz +0 -0
  120. data/spec/rhc/auth_spec.rb +442 -0
  121. data/spec/rhc/cli_spec.rb +186 -0
  122. data/spec/rhc/command_spec.rb +435 -0
  123. data/spec/rhc/commands/account_spec.rb +42 -0
  124. data/spec/rhc/commands/alias_spec.rb +333 -0
  125. data/spec/rhc/commands/app_spec.rb +777 -0
  126. data/spec/rhc/commands/apps_spec.rb +39 -0
  127. data/spec/rhc/commands/authorization_spec.rb +157 -0
  128. data/spec/rhc/commands/cartridge_spec.rb +665 -0
  129. data/spec/rhc/commands/clone_spec.rb +41 -0
  130. data/spec/rhc/commands/deployment_spec.rb +327 -0
  131. data/spec/rhc/commands/domain_spec.rb +401 -0
  132. data/spec/rhc/commands/env_spec.rb +493 -0
  133. data/spec/rhc/commands/git_clone_spec.rb +102 -0
  134. data/spec/rhc/commands/logout_spec.rb +86 -0
  135. data/spec/rhc/commands/member_spec.rb +247 -0
  136. data/spec/rhc/commands/port_forward_spec.rb +217 -0
  137. data/spec/rhc/commands/scp_spec.rb +77 -0
  138. data/spec/rhc/commands/server_spec.rb +69 -0
  139. data/spec/rhc/commands/setup_spec.rb +118 -0
  140. data/spec/rhc/commands/snapshot_spec.rb +179 -0
  141. data/spec/rhc/commands/ssh_spec.rb +163 -0
  142. data/spec/rhc/commands/sshkey_spec.rb +188 -0
  143. data/spec/rhc/commands/tail_spec.rb +81 -0
  144. data/spec/rhc/commands/threaddump_spec.rb +84 -0
  145. data/spec/rhc/config_spec.rb +407 -0
  146. data/spec/rhc/helpers_spec.rb +531 -0
  147. data/spec/rhc/highline_extensions_spec.rb +314 -0
  148. data/spec/rhc/json_spec.rb +30 -0
  149. data/spec/rhc/rest_application_spec.rb +258 -0
  150. data/spec/rhc/rest_client_spec.rb +752 -0
  151. data/spec/rhc/rest_spec.rb +740 -0
  152. data/spec/rhc/targz_spec.rb +55 -0
  153. data/spec/rhc/wizard_spec.rb +756 -0
  154. data/spec/spec_helper.rb +575 -0
  155. data/spec/wizard_spec_helper.rb +330 -0
  156. metadata +469 -0
@@ -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