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