corl 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. data/.document +5 -0
  2. data/.gitmodules +4 -0
  3. data/Gemfile +24 -0
  4. data/Gemfile.lock +123 -0
  5. data/LICENSE.txt +674 -0
  6. data/README.rdoc +27 -0
  7. data/Rakefile +78 -0
  8. data/VERSION +1 -0
  9. data/bin/corl +55 -0
  10. data/corl.gemspec +228 -0
  11. data/lib/corl/action/add.rb +69 -0
  12. data/lib/corl/action/bootstrap.rb +83 -0
  13. data/lib/corl/action/clone.rb +40 -0
  14. data/lib/corl/action/create.rb +55 -0
  15. data/lib/corl/action/exec.rb +41 -0
  16. data/lib/corl/action/extract.rb +49 -0
  17. data/lib/corl/action/image.rb +30 -0
  18. data/lib/corl/action/images.rb +55 -0
  19. data/lib/corl/action/lookup.rb +35 -0
  20. data/lib/corl/action/machines.rb +51 -0
  21. data/lib/corl/action/provision.rb +37 -0
  22. data/lib/corl/action/remove.rb +51 -0
  23. data/lib/corl/action/save.rb +53 -0
  24. data/lib/corl/action/seed.rb +115 -0
  25. data/lib/corl/action/spawn.rb +75 -0
  26. data/lib/corl/action/start.rb +37 -0
  27. data/lib/corl/action/stop.rb +30 -0
  28. data/lib/corl/action/update.rb +37 -0
  29. data/lib/corl/command/shell.rb +164 -0
  30. data/lib/corl/configuration/file.rb +386 -0
  31. data/lib/corl/event/puppet.rb +90 -0
  32. data/lib/corl/event/regex.rb +52 -0
  33. data/lib/corl/extension/puppetloader.rb +24 -0
  34. data/lib/corl/machine/fog.rb +310 -0
  35. data/lib/corl/machine/physical.rb +161 -0
  36. data/lib/corl/network/default.rb +26 -0
  37. data/lib/corl/node/aws.rb +90 -0
  38. data/lib/corl/node/fog.rb +198 -0
  39. data/lib/corl/node/google.rb +115 -0
  40. data/lib/corl/node/local.rb +26 -0
  41. data/lib/corl/node/rackspace.rb +89 -0
  42. data/lib/corl/project/git.rb +465 -0
  43. data/lib/corl/project/github.rb +108 -0
  44. data/lib/corl/provisioner/puppetnode/resource.rb +245 -0
  45. data/lib/corl/provisioner/puppetnode/resource_group.rb +205 -0
  46. data/lib/corl/provisioner/puppetnode.rb +407 -0
  47. data/lib/corl/template/environment.rb +73 -0
  48. data/lib/corl/template/json.rb +16 -0
  49. data/lib/corl/template/wrapper.rb +16 -0
  50. data/lib/corl/template/yaml.rb +16 -0
  51. data/lib/corl/translator/json.rb +27 -0
  52. data/lib/corl/translator/yaml.rb +27 -0
  53. data/lib/corl.rb +173 -0
  54. data/lib/corl_core/codes.rb +107 -0
  55. data/lib/corl_core/config/collection.rb +57 -0
  56. data/lib/corl_core/config/options.rb +70 -0
  57. data/lib/corl_core/config.rb +337 -0
  58. data/lib/corl_core/core.rb +59 -0
  59. data/lib/corl_core/corl.rb +254 -0
  60. data/lib/corl_core/errors.rb +84 -0
  61. data/lib/corl_core/facade.rb +126 -0
  62. data/lib/corl_core/gems.rb +72 -0
  63. data/lib/corl_core/manager.rb +425 -0
  64. data/lib/corl_core/mixin/action/commit.rb +58 -0
  65. data/lib/corl_core/mixin/action/keypair.rb +105 -0
  66. data/lib/corl_core/mixin/action/node.rb +129 -0
  67. data/lib/corl_core/mixin/action/project.rb +53 -0
  68. data/lib/corl_core/mixin/action/push.rb +52 -0
  69. data/lib/corl_core/mixin/config/collection.rb +53 -0
  70. data/lib/corl_core/mixin/config/ops.rb +53 -0
  71. data/lib/corl_core/mixin/config/options.rb +39 -0
  72. data/lib/corl_core/mixin/lookup.rb +196 -0
  73. data/lib/corl_core/mixin/macro/object_interface.rb +361 -0
  74. data/lib/corl_core/mixin/macro/plugin_interface.rb +380 -0
  75. data/lib/corl_core/mixin/settings.rb +46 -0
  76. data/lib/corl_core/mixin/sub_config.rb +148 -0
  77. data/lib/corl_core/mod/hash.rb +29 -0
  78. data/lib/corl_core/mod/hiera_backend.rb +63 -0
  79. data/lib/corl_core/plugin/action.rb +381 -0
  80. data/lib/corl_core/plugin/base.rb +374 -0
  81. data/lib/corl_core/plugin/command.rb +98 -0
  82. data/lib/corl_core/plugin/configuration.rb +177 -0
  83. data/lib/corl_core/plugin/event.rb +53 -0
  84. data/lib/corl_core/plugin/extension.rb +12 -0
  85. data/lib/corl_core/plugin/machine.rb +266 -0
  86. data/lib/corl_core/plugin/network.rb +359 -0
  87. data/lib/corl_core/plugin/node.rb +904 -0
  88. data/lib/corl_core/plugin/project.rb +927 -0
  89. data/lib/corl_core/plugin/provisioner.rb +51 -0
  90. data/lib/corl_core/plugin/template.rb +80 -0
  91. data/lib/corl_core/plugin/translator.rb +38 -0
  92. data/lib/corl_core/util/cli.rb +352 -0
  93. data/lib/corl_core/util/data.rb +404 -0
  94. data/lib/corl_core/util/disk.rb +114 -0
  95. data/lib/corl_core/util/git.rb +47 -0
  96. data/lib/corl_core/util/interface.rb +319 -0
  97. data/lib/corl_core/util/liquid.rb +17 -0
  98. data/lib/corl_core/util/package.rb +93 -0
  99. data/lib/corl_core/util/shell.rb +239 -0
  100. data/lib/corl_core/util/ssh.rb +286 -0
  101. data/lib/facter/corl_config_ready.rb +13 -0
  102. data/lib/facter/corl_exists.rb +15 -0
  103. data/lib/facter/corl_network.rb +17 -0
  104. data/lib/hiera/corl_logger.rb +18 -0
  105. data/lib/puppet/indirector/corl.rb +27 -0
  106. data/lib/puppet/indirector/data_binding/corl.rb +6 -0
  107. data/lib/puppet/parser/functions/config_initialized.rb +26 -0
  108. data/lib/puppet/parser/functions/corl_include.rb +44 -0
  109. data/lib/puppet/parser/functions/corl_resources.rb +58 -0
  110. data/lib/puppet/parser/functions/deep_merge.rb +21 -0
  111. data/lib/puppet/parser/functions/ensure.rb +29 -0
  112. data/lib/puppet/parser/functions/file_exists.rb +19 -0
  113. data/lib/puppet/parser/functions/global_array.rb +35 -0
  114. data/lib/puppet/parser/functions/global_hash.rb +35 -0
  115. data/lib/puppet/parser/functions/global_options.rb +23 -0
  116. data/lib/puppet/parser/functions/global_param.rb +43 -0
  117. data/lib/puppet/parser/functions/interpolate.rb +26 -0
  118. data/lib/puppet/parser/functions/is_false.rb +21 -0
  119. data/lib/puppet/parser/functions/is_true.rb +21 -0
  120. data/lib/puppet/parser/functions/module_array.rb +38 -0
  121. data/lib/puppet/parser/functions/module_hash.rb +38 -0
  122. data/lib/puppet/parser/functions/module_options.rb +23 -0
  123. data/lib/puppet/parser/functions/module_param.rb +48 -0
  124. data/lib/puppet/parser/functions/name.rb +21 -0
  125. data/lib/puppet/parser/functions/render.rb +33 -0
  126. data/lib/puppet/parser/functions/value.rb +21 -0
  127. data/locales/en.yml +232 -0
  128. data/spec/corl_core/interface_spec.rb +489 -0
  129. data/spec/corl_mock_input.rb +29 -0
  130. data/spec/corl_test_kernel.rb +22 -0
  131. data/spec/spec_helper.rb +15 -0
  132. metadata +406 -0
@@ -0,0 +1,337 @@
1
+
2
+ module CORL
3
+ class Config
4
+
5
+ #-----------------------------------------------------------------------------
6
+ # Global interface
7
+
8
+ extend Mixin::ConfigOptions
9
+ extend Mixin::ConfigCollection
10
+ extend Mixin::Lookup
11
+
12
+ #-----------------------------------------------------------------------------
13
+ # Instance generators
14
+
15
+ def self.ensure(config)
16
+ case config
17
+ when CORL::Config
18
+ return config
19
+ when Hash
20
+ return new(config)
21
+ end
22
+ return new
23
+ end
24
+
25
+ #---
26
+
27
+ def self.init(options, contexts = [], hierarchy = [], defaults = {})
28
+ contexts = contexts(contexts, hierarchy)
29
+ config = new(get_options(contexts), defaults)
30
+ config.import(options) unless Util::Data.empty?(options)
31
+ return config
32
+ end
33
+
34
+ #---
35
+
36
+ def self.init_flat(options, contexts = [], defaults = {})
37
+ return init(options, contexts, [], defaults)
38
+ end
39
+
40
+ #-----------------------------------------------------------------------------
41
+ # Constructor / Destructor
42
+
43
+ def initialize(data = {}, defaults = {}, force = true)
44
+ @force = force
45
+ @properties = {}
46
+
47
+ if defaults.is_a?(Hash) && ! defaults.empty?
48
+ defaults = symbol_map(defaults)
49
+ end
50
+
51
+ case data
52
+ when CORL::Config
53
+ @properties = Util::Data.merge([ defaults, data.export ], force)
54
+ when Hash
55
+ @properties = {}
56
+ if data.is_a?(Hash)
57
+ @properties = Util::Data.merge([ defaults, symbol_map(data) ], force)
58
+ end
59
+ end
60
+ end
61
+
62
+ #-----------------------------------------------------------------------------
63
+ # Checks
64
+
65
+ def has_key?(keys)
66
+ get(keys) ? true : false
67
+ end
68
+
69
+ #-----------------------------------------------------------------------------
70
+ # Property accessors / modifiers
71
+
72
+ def keys
73
+ @properties.keys
74
+ end
75
+
76
+ #---
77
+
78
+ def fetch(data, keys, default = nil, format = false)
79
+ if keys.is_a?(String) || keys.is_a?(Symbol)
80
+ keys = [ keys ]
81
+ end
82
+ key = keys.shift.to_sym
83
+
84
+ if data.has_key?(key)
85
+ value = data[key]
86
+
87
+ if keys.empty?
88
+ return filter(value, format)
89
+ else
90
+ return fetch(data[key], keys, default, format)
91
+ end
92
+ end
93
+ return filter(default, format)
94
+ end
95
+ protected :fetch
96
+
97
+ #---
98
+
99
+ def modify(data, keys, value = nil)
100
+ if keys.is_a?(String) || keys.is_a?(Symbol)
101
+ keys = [ keys ]
102
+ end
103
+
104
+ key = keys.shift.to_sym
105
+ has_key = data.has_key?(key)
106
+ existing = {
107
+ :key => key,
108
+ :value => ( has_key ? data[key] : nil )
109
+ }
110
+
111
+ if keys.empty?
112
+ existing[:value] = data[key] if has_key
113
+
114
+ if value.nil?
115
+ data.delete(key) if has_key
116
+ else
117
+ data[key] = value
118
+ end
119
+ else
120
+ data[key] = {} unless has_key
121
+ existing = modify(data[key], keys, value)
122
+ end
123
+
124
+ return existing
125
+ end
126
+ protected :modify
127
+
128
+ #---
129
+
130
+ def get(keys, default = nil, format = false)
131
+ return fetch(@properties, array(keys).flatten, default, format)
132
+ end
133
+
134
+ #---
135
+
136
+ def [](name, default = nil, format = false)
137
+ get(name, default, format)
138
+ end
139
+
140
+ #---
141
+
142
+ def get_array(keys, default = [])
143
+ return get(keys, default, :array)
144
+ end
145
+
146
+ #---
147
+
148
+ def get_hash(keys, default = {})
149
+ return get(keys, default, :hash)
150
+ end
151
+
152
+ #---
153
+
154
+ def init(keys, default = nil)
155
+ return set(keys, get(keys, default))
156
+ end
157
+
158
+ #---
159
+
160
+ def set(keys, value)
161
+ modify(@properties, array(keys).flatten, value)
162
+ return self
163
+ end
164
+
165
+ #---
166
+
167
+ def []=(name, value)
168
+ set(name, value)
169
+ end
170
+
171
+ #---
172
+
173
+ def delete(keys, default = nil)
174
+ existing = modify(@properties, array(keys).flatten, nil)
175
+ return existing[:value] if existing[:value]
176
+ return default
177
+ end
178
+
179
+ #---
180
+
181
+ def clear
182
+ @properties = {}
183
+ return self
184
+ end
185
+
186
+ #-----------------------------------------------------------------------------
187
+ # Import / Export
188
+
189
+ def import_base(properties, options = {})
190
+ config = Config.new(options, { :force => @force }).set(:context, :hash)
191
+ import_type = config.get(:import_type, :override)
192
+
193
+ properties = properties.export if properties.is_a?(CORL::Config)
194
+
195
+ case properties
196
+ when Hash
197
+ data = [ @properties, symbol_map(properties) ]
198
+ data = data.reverse if import_type != :override
199
+
200
+ @properties = Util::Data.merge(data, config)
201
+
202
+ when String, Symbol
203
+ properties = self.class.lookup(properties.to_s, {}, config)
204
+
205
+ data = [ @properties, symbol_map(properties) ]
206
+ data = data.reverse if import_type != :override
207
+
208
+ @properties = Util::Data.merge(data, config)
209
+
210
+ when Array
211
+ properties.each do |item|
212
+ import_base(item, config)
213
+ end
214
+ end
215
+
216
+ return self
217
+ end
218
+ protected :import_base
219
+
220
+ #---
221
+
222
+ def import(properties, options = {})
223
+ return import_base(properties, options)
224
+ end
225
+
226
+ #---
227
+
228
+ def defaults(defaults, options = {})
229
+ config = Config.new(options).set(:import_type, :default)
230
+ return import_base(defaults, config)
231
+ end
232
+
233
+ #---
234
+
235
+ def export
236
+ return @properties
237
+ end
238
+
239
+ #-----------------------------------------------------------------------------
240
+ # Utilities
241
+
242
+ def self.symbol_map(data)
243
+ return Util::Data.symbol_map(data)
244
+ end
245
+
246
+ #---
247
+
248
+ def symbol_map(data)
249
+ return self.class.symbol_map(data)
250
+ end
251
+
252
+ #---
253
+
254
+ def self.string_map(data)
255
+ return Util::Data.string_map(data)
256
+ end
257
+
258
+ #---
259
+
260
+ def string_map(data)
261
+ return self.class.string_map(data)
262
+ end
263
+
264
+ #-----------------------------------------------------------------------------
265
+
266
+ def self.filter(data, method = false)
267
+ return Util::Data.filter(data, method)
268
+ end
269
+
270
+ #---
271
+
272
+ def filter(data, method = false)
273
+ return self.class.filter(data, method)
274
+ end
275
+
276
+ #-----------------------------------------------------------------------------
277
+
278
+ def self.array(data, default = [], split_string = false)
279
+ return Util::Data.array(data, default, split_string)
280
+ end
281
+
282
+ #---
283
+
284
+ def array(data, default = [], split_string = false)
285
+ return self.class.array(data, default, split_string)
286
+ end
287
+
288
+ #---
289
+
290
+ def self.hash(data, default = {})
291
+ data = data.export if data.is_a?(CORL::Config)
292
+ return Util::Data.hash(data, default)
293
+ end
294
+
295
+ #---
296
+
297
+ def hash(data, default = {})
298
+ return self.class.hash(data, default)
299
+ end
300
+
301
+ #---
302
+
303
+ def self.string(data, default = '')
304
+ return Util::Data.string(data, default)
305
+ end
306
+
307
+ #---
308
+
309
+ def string(data, default = '')
310
+ return self.class.string(data, default)
311
+ end
312
+
313
+ #---
314
+
315
+ def self.symbol(data, default = :undefined)
316
+ return Util::Data.symbol(data, default)
317
+ end
318
+
319
+ #---
320
+
321
+ def symbol(data, default = :undefined)
322
+ return self.class.symbol(data, default)
323
+ end
324
+
325
+ #---
326
+
327
+ def self.test(data)
328
+ return Util::Data.test(data)
329
+ end
330
+
331
+ #---
332
+
333
+ def test(data)
334
+ return self.class.test(data)
335
+ end
336
+ end
337
+ end
@@ -0,0 +1,59 @@
1
+
2
+ module CORL
3
+ class Core < Config
4
+
5
+ #-----------------------------------------------------------------------------
6
+ # Properties
7
+
8
+ @@ui = Util::Interface.new("core")
9
+
10
+ #-----------------------------------------------------------------------------
11
+ # Constructor / Destructor
12
+
13
+ def initialize(data = {}, defaults = {}, force = true)
14
+ super(data, defaults, force)
15
+
16
+ class_label = self.class.to_s.downcase.gsub(/^corl::/, '')
17
+ logger_name = delete(:logger, class_label)
18
+ interface_config = Config.new(export).defaults({ :logger => logger_name, :resource => class_label })
19
+
20
+ @ui = Util::Interface.new(interface_config)
21
+ logger.debug("Initialized instance interface")
22
+ end
23
+
24
+ #-----------------------------------------------------------------------------
25
+ # Accessor / Modifiers
26
+
27
+ attr_accessor :ui
28
+
29
+ #---
30
+
31
+ def self.ui
32
+ return @@ui
33
+ end
34
+
35
+ #---
36
+
37
+ def self.logger
38
+ return @@ui.logger
39
+ end
40
+
41
+ #---
42
+
43
+ def logger
44
+ return @ui.logger
45
+ end
46
+
47
+ #-----------------------------------------------------------------------------
48
+ # General utilities
49
+
50
+ def ui_group(resource)
51
+ ui_resource = ui.resource
52
+ ui.resource = resource
53
+ yield
54
+
55
+ ensure
56
+ ui.resource = ui_resource
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,254 @@
1
+
2
+ module CORL
3
+
4
+ VERSION = File.read(File.join(File.dirname(__FILE__), '..', '..', 'VERSION'))
5
+
6
+ #-----------------------------------------------------------------------------
7
+
8
+ def self.ui
9
+ Core.ui
10
+ end
11
+
12
+ #---
13
+
14
+ def self.logger
15
+ Core.logger
16
+ end
17
+
18
+ #---
19
+
20
+ def self.add_log_levels(*levels)
21
+ Util::Interface.add_log_levels(levels)
22
+ end
23
+
24
+ def self.log_level
25
+ Util::Interface.log_level
26
+ end
27
+
28
+ def self.log_level=log_level
29
+ Util::Interface.log_level = log_level
30
+ end
31
+
32
+ #-----------------------------------------------------------------------------
33
+
34
+ def self.admin?
35
+ is_admin = ( ENV['USER'] == 'root' )
36
+ ext_admin = exec(:check_admin) do |op, results|
37
+ if op == :reduce
38
+ results.values.include?(true)
39
+ else
40
+ results ? true : false
41
+ end
42
+ end
43
+ is_admin || ext_admin ? true : false
44
+ end
45
+
46
+ #-----------------------------------------------------------------------------
47
+ # Status codes
48
+
49
+ @@codes = Codes.new
50
+
51
+ def self.code
52
+ @@codes
53
+ end
54
+
55
+ def self.codes(*codes)
56
+ Codes.codes(*codes)
57
+ end
58
+
59
+ #-----------------------------------------------------------------------------
60
+ # Initialization
61
+
62
+ def self.initialize
63
+ current_time = Time.now
64
+
65
+ Celluloid.logger = logger
66
+
67
+ logger.info("Initializing the CORL plugin system at #{current_time}")
68
+ Config.set_property('time', current_time.to_i)
69
+
70
+ connection = Manager.connection
71
+
72
+ connection.define_type :extension => nil, # Core
73
+ :configuration => :file, # Core
74
+ :action => :update, # Core
75
+ :project => :git, # Core
76
+ :network => :default, # Cluster
77
+ :node => :local, # Cluster
78
+ :machine => :physical, # Cluster
79
+ :provisioner => :puppetnode, # Cluster
80
+ :command => :shell, # Cluster
81
+ :event => :regex, # Utility
82
+ :template => :json, # Utility
83
+ :translator => :json # Utility
84
+
85
+ connection.load_plugins(true)
86
+
87
+ logger.info("Finished initializing CORL plugin system at #{Time.now}")
88
+ end
89
+
90
+ #-----------------------------------------------------------------------------
91
+ # Core plugin interface
92
+
93
+ def self.plugin_load(type, provider, options = {})
94
+ config = Config.ensure(options)
95
+ name = config.get(:name, nil)
96
+
97
+ logger.info("Fetching plugin #{type} provider #{provider} at #{Time.now}")
98
+ logger.debug("Plugin options: #{config.export.inspect}")
99
+
100
+ connection = Manager.connection
101
+
102
+ if name
103
+ logger.debug("Looking up existing instance of #{name}")
104
+
105
+ existing_instance = connection.get(type, name)
106
+ logger.info("Using existing instance of #{type}, #{name}") if existing_instance
107
+ end
108
+
109
+ return existing_instance if existing_instance
110
+ connection.create(type, provider, config.export)
111
+ end
112
+
113
+ #---
114
+
115
+ def self.plugin(type, provider, options = {})
116
+ default_provider = Manager.connection.type_default(type)
117
+
118
+ if options.is_a?(Hash) || options.is_a?(CORL::Config)
119
+ config = Config.ensure(options)
120
+ provider = config.get(:provider, provider)
121
+ options = config.export
122
+ end
123
+ provider = default_provider unless provider # Sanity checking (see plugins)
124
+
125
+ plugin_load(type, provider, options)
126
+ end
127
+
128
+ #---
129
+
130
+ def self.plugins(type, data, build_hash = false, keep_array = false)
131
+ logger.info("Fetching multiple plugins of #{type} at #{Time.now}")
132
+
133
+ group = ( build_hash ? {} : [] )
134
+ klass = class_const([ 'CORL', :plugin, type ])
135
+ data = klass.build_info(type, data) if klass.respond_to?(:build_info)
136
+
137
+ logger.debug("Translated plugin data: #{data.inspect}")
138
+
139
+ data.each do |options|
140
+ if plugin = plugin(type, options[:provider], options)
141
+ if build_hash
142
+ group[plugin.plugin_name] = plugin
143
+ else
144
+ group << plugin
145
+ end
146
+ end
147
+ end
148
+ return group.shift if ! build_hash && group.length == 1 && ! keep_array
149
+ group
150
+ end
151
+
152
+ #---
153
+
154
+ def self.get_plugin(type, name)
155
+ Manager.connection.get(type, name)
156
+ end
157
+
158
+ #---
159
+
160
+ def self.remove_plugin(plugin)
161
+ Manager.connection.remove(plugin)
162
+ end
163
+
164
+ #-----------------------------------------------------------------------------
165
+ # Plugin extensions
166
+
167
+ def self.exec(method, options = {})
168
+ Manager.connection.exec(method, options) do |op, data|
169
+ data = yield(op, data) if block_given?
170
+ data
171
+ end
172
+ end
173
+
174
+ #---
175
+
176
+ def self.config(type, options = {})
177
+ Manager.connection.config(method, options)
178
+ end
179
+
180
+ #---
181
+
182
+ def self.check(method, options = {})
183
+ Manager.connection.check(method, options)
184
+ end
185
+
186
+ #---
187
+
188
+ def self.value(method, value, options = {})
189
+ Manager.connection.value(method, value, options)
190
+ end
191
+
192
+ #-----------------------------------------------------------------------------
193
+ # External execution
194
+
195
+ def self.run
196
+ begin
197
+ logger.debug("Running contained process at #{Time.now}")
198
+ yield
199
+
200
+ rescue Exception => error
201
+ logger.error("CORL run experienced an error! Details:")
202
+ logger.error(error.inspect)
203
+ logger.error(error.message)
204
+ logger.error(Util::Data.to_yaml(error.backtrace))
205
+
206
+ ui.error(error.message) if error.message
207
+ raise
208
+ end
209
+ end
210
+
211
+ #-----------------------------------------------------------------------------
212
+ # Utilities
213
+
214
+ def self.class_name(name, separator = '::', want_array = FALSE)
215
+ components = []
216
+
217
+ case name
218
+ when String, Symbol
219
+ components = name.to_s.split(separator)
220
+ when Array
221
+ components = name
222
+ end
223
+
224
+ components.collect! do |value|
225
+ next value if value.to_s == 'CORL'
226
+ value.to_s.strip.capitalize
227
+ end
228
+
229
+ if want_array
230
+ return components
231
+ end
232
+ components.join(separator)
233
+ end
234
+
235
+ #---
236
+
237
+ def self.class_const(name, separator = '::')
238
+ components = class_name(name, separator, TRUE)
239
+ constant = Object
240
+
241
+ components.each do |component|
242
+ constant = constant.const_defined?(component) ?
243
+ constant.const_get(component) :
244
+ constant.const_missing(component)
245
+ end
246
+ constant
247
+ end
248
+
249
+ #---
250
+
251
+ def self.sha1(data)
252
+ Digest::SHA1.hexdigest(Util::Data.to_json(data, false))
253
+ end
254
+ end
@@ -0,0 +1,84 @@
1
+
2
+ module CORL
3
+ module Errors
4
+
5
+ #-----------------------------------------------------------------------------
6
+ # Base error (based on VagrantError)
7
+
8
+ class CORLError < StandardError
9
+
10
+ #---------------------------------------------------------------------------
11
+ # Error constructor / destructor
12
+
13
+ def initialize(*args)
14
+ key = args.shift if args.first.is_a?(Symbol)
15
+ message = args.shift if args.first.is_a?(Hash)
16
+ message ||= {}
17
+
18
+ @extra_data = message.dup
19
+
20
+ message[:key] ||= error_key
21
+ message[:namespace] ||= error_namespace
22
+ message[:key] = key if key
23
+
24
+ if message[:key]
25
+ message = translate_error(message)
26
+ else
27
+ message = error_message
28
+ end
29
+
30
+ super(message)
31
+ end
32
+
33
+ #---------------------------------------------------------------------------
34
+ # Property accessor / modifiers
35
+
36
+ attr_accessor :extra_data
37
+
38
+ #---
39
+
40
+ def self.error_key(key = nil, namespace = nil)
41
+ define_method(:error_key) { key }
42
+ error_namespace(namespace) if namespace
43
+ end
44
+ def error_key; nil; end # Default
45
+
46
+ #---
47
+
48
+ def self.error_message(message)
49
+ define_method(:error_message) { message }
50
+ end
51
+ def error_message; "No error message"; end # Default
52
+
53
+ #---
54
+
55
+ def self.error_namespace(namespace)
56
+ define_method(:error_namespace) { namespace }
57
+ end
58
+ def error_namespace; "corl.errors"; end # Default
59
+
60
+ #---
61
+
62
+ def self.status_code(code)
63
+ define_method(:status_code) { code }
64
+ end
65
+ def status_code; 1; end # Default
66
+
67
+ #---------------------------------------------------------------------------
68
+ # Utilities
69
+
70
+ def translate_error(options)
71
+ return nil unless options[:key]
72
+ I18n.t("#{options[:namespace]}.#{options[:key]}", options)
73
+ end
74
+ protected :translate_error
75
+ end
76
+
77
+ #-----------------------------------------------------------------------------
78
+ # Specialized errors
79
+
80
+ class BatchError < CORLError
81
+ error_key(:batch_error)
82
+ end
83
+ end
84
+ end