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,164 @@
1
+
2
+ module CORL
3
+ module Command
4
+ class Shell < Plugin::Command
5
+
6
+ #-----------------------------------------------------------------------------
7
+ # Command plugin interface
8
+
9
+ def normalize
10
+ super
11
+ command = executable(self)
12
+
13
+ logger.info("Setting command executable to #{command}")
14
+ set(:command, command)
15
+ end
16
+
17
+ #-----------------------------------------------------------------------------
18
+ # Command operations
19
+
20
+ def build(components = {}, overrides = nil, override_key = false)
21
+ command = string(components[:command])
22
+ flags = array( components.has_key?(:flags) ? components[:flags] : [] )
23
+ data = string_map(hash( components.has_key?(:data) ? components[:data] : {} ))
24
+ args = array( components.has_key?(:args) ? components[:args] : [] )
25
+ subcommand = hash( components.has_key?(:subcommand) ? components[:subcommand] : {} )
26
+
27
+ override_key = command unless override_key
28
+ override_key = override_key.to_sym
29
+
30
+ command_string = command.dup
31
+ subcommand_string = ''
32
+
33
+ escape_characters = /[\'\"]+/
34
+ escape_replacement = '\"'
35
+
36
+ dash_pattern = /^([\-]+)/
37
+ assignment_pattern = /\=$/
38
+
39
+ logger.info("Building command #{command}")
40
+ logger.debug("Command flags: #{flags.inspect}")
41
+ logger.debug("Command options: #{data.inspect}")
42
+ logger.debug("Command arguments: #{args.inspect}")
43
+ logger.debug("Command has sub command") unless subcommand.empty?
44
+
45
+ logger.debug("Overrides: #{overrides.inspect}")
46
+ logger.debug("Override key: #{override_key}")
47
+
48
+ # Flags
49
+ if overrides && overrides.has_key?(:flags)
50
+ if overrides[:flags].is_a?(Hash)
51
+ if overrides[:flags].has_key?(override_key)
52
+ flags = array(overrides[:flags][override_key])
53
+ end
54
+ else
55
+ flags = array(overrides[:flags])
56
+ end
57
+ end
58
+ flags.each do |flag|
59
+ flag = string(flag)
60
+ if ! flag.empty?
61
+ if flag.match(dash_pattern)
62
+ dashes = $1
63
+ else
64
+ dashes = ( flag.size == 1 ? '-' : '--' )
65
+ end
66
+ command_string << " #{dashes}#{flag}"
67
+ end
68
+ end
69
+
70
+ # Data
71
+ if overrides && overrides.has_key?(:data)
72
+ if overrides[:data].has_key?(override_key)
73
+ data = hash(overrides[:data][override_key])
74
+ else
75
+ override = true
76
+ overrides[:data].each do |key, value|
77
+ if ! value.is_a?(String)
78
+ override = false
79
+ end
80
+ end
81
+ data = hash(overrides[:data]) if override
82
+ end
83
+ end
84
+ data.each do |key, value|
85
+ key = string(key)
86
+ value = string(value).strip.sub(escape_characters, escape_replacement)
87
+
88
+ if key.match(dash_pattern)
89
+ dashes = $1
90
+ else
91
+ dashes = ( key.size == 1 ? '-' : '--' )
92
+ end
93
+ space = ( key.match(assignment_pattern) ? '' : ' ' )
94
+
95
+ command_string << " #{dashes}#{key}#{space}\"#{value}\""
96
+ end
97
+
98
+ # Arguments
99
+ if overrides && overrides.has_key?(:args)
100
+ unless overrides[:args].empty?
101
+ if overrides[:args].is_a?(Hash)
102
+ if overrides[:args].has_key?(override_key)
103
+ args = array(overrides[:args][override_key])
104
+ end
105
+ else
106
+ args = array(overrides[:args])
107
+ end
108
+ end
109
+ end
110
+ args.each do |arg|
111
+ arg = string(arg).sub(escape_characters, escape_replacement)
112
+
113
+ unless arg.empty?
114
+ command_string << " \"#{arg}\""
115
+ end
116
+ end
117
+
118
+ # Subcommand
119
+ subcommand_overrides = ( overrides ? overrides[:subcommand] : nil )
120
+ if subcommand && subcommand.is_a?(Hash) && ! subcommand.empty?
121
+ subcommand_string = build(subcommand, subcommand_overrides)
122
+ end
123
+
124
+ command_string = (command_string + ' ' + subcommand_string).strip
125
+
126
+ logger.debug("Rendered command: #{command_string}")
127
+ return command_string
128
+ end
129
+
130
+ #---
131
+
132
+ def exec(options = {}, overrides = nil)
133
+ config = Config.ensure(options)
134
+
135
+ logger.info("Executing command #{command}")
136
+
137
+ config[:ui] = @ui
138
+ result = Util::Shell.connection.exec(build(export, overrides), config) do |op, command, data|
139
+ block_given? ? yield(op, command, data) : true
140
+ end
141
+
142
+ logger.warn("Command #{command} failed to execute") unless result.status == CORL.code.success
143
+ return result
144
+ end
145
+
146
+ #-----------------------------------------------------------------------------
147
+ # Utilities
148
+
149
+ def executable(options)
150
+ config = Config.ensure(options)
151
+
152
+ if config.get(:corl, false)
153
+ return 'corl ' + config[:corl]
154
+
155
+ elsif config.get(:vagrant, false)
156
+ return 'vagrant ' + config[:vagrant]
157
+
158
+ elsif config.get(:command, false)
159
+ return config[:command]
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,386 @@
1
+
2
+ module CORL
3
+ module Configuration
4
+ class File < Plugin::Configuration
5
+
6
+ #-----------------------------------------------------------------------------
7
+ # Configuration plugin interface
8
+
9
+ def normalize
10
+ super
11
+
12
+ logger.info("Setting source configuration project")
13
+ @project = CORL.project(extended_config(:project, {
14
+ :directory => _delete(:directory, Dir.pwd),
15
+ :url => _delete(:url),
16
+ :revision => _delete(:revision)
17
+ }), _delete(:project_provider))
18
+
19
+ _set(:search, Config.new)
20
+ _set(:router, Config.new)
21
+
22
+ set_location(@project)
23
+ end
24
+
25
+ #---
26
+
27
+ def self.finalize(file_name)
28
+ proc do
29
+ logger.debug("Finalizing file: #{file_name}")
30
+ Util::Disk.close(file_name)
31
+ end
32
+ end
33
+
34
+ #-----------------------------------------------------------------------------
35
+ # Checks
36
+
37
+ def can_persist?
38
+ project.can_persist?
39
+ end
40
+
41
+ #-----------------------------------------------------------------------------
42
+ # Property accessors / modifiers
43
+
44
+ def project
45
+ @project
46
+ end
47
+
48
+ #---
49
+
50
+ def search
51
+ _get(:search)
52
+ end
53
+
54
+ #---
55
+
56
+ def router
57
+ _get(:router)
58
+ end
59
+
60
+ #-----------------------------------------------------------------------------
61
+
62
+ def set_location(directory)
63
+ if directory && directory.is_a?(CORL::Plugin::Project)
64
+ logger.debug("Setting source project directory from other project at #{directory.directory}")
65
+ project.set_location(directory.directory)
66
+
67
+ elsif directory && directory.is_a?(String) || directory.is_a?(Symbol)
68
+ logger.debug("Setting source project directory to #{directory}")
69
+ project.set_location(directory.to_s)
70
+ end
71
+ search_files if directory
72
+ end
73
+
74
+ #---
75
+
76
+ def remote(name)
77
+ project.remote(name)
78
+ end
79
+
80
+ #---
81
+
82
+ def set_remote(name, location)
83
+ project.set_remote(name, location)
84
+ end
85
+
86
+ #-----------------------------------------------------------------------------
87
+ # Configuration loading / saving
88
+
89
+ def load(options = {})
90
+ super do |method_config, properties|
91
+
92
+ generate_routes = lambda do |config_name, file_properties, parents = []|
93
+ file_properties.each do |name, value|
94
+ keys = [ parents, name ].flatten
95
+
96
+ if value.is_a?(Hash) && ! value.empty?
97
+ generate_routes.call(config_name, value, keys)
98
+ else
99
+ router.set(keys, config_name)
100
+ end
101
+ end
102
+ end
103
+
104
+ if fetch_project(method_config)
105
+ search.export.each do |config_name, info|
106
+ provider = info[:provider]
107
+ file = info[:file]
108
+
109
+ logger.info("Loading #{provider} translated source configuration from #{file}")
110
+
111
+ parser = CORL.translator(method_config, provider)
112
+ raw = Util::Disk.read(file)
113
+
114
+ if parser && raw && ! raw.empty?
115
+ logger.debug("Source configuration file contents: #{raw}")
116
+ file_properties = parser.parse(raw)
117
+
118
+ generate_routes.call(config_name, file_properties)
119
+ properties.import(file_properties)
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+ #---
127
+
128
+ # properties[key...] = values
129
+ #
130
+ # to
131
+ #
132
+ # file_data[config_name][key...] = config
133
+
134
+ def separate
135
+ file_data = Config.new
136
+
137
+ split_config = lambda do |properties, local_router, parents = []|
138
+ properties.each do |name, value|
139
+ keys = [ parents, name ].flatten
140
+
141
+ if value.is_a?(Hash) && ! value.empty?
142
+ # Nested configurations
143
+ if local_router.is_a?(Hash) && local_router.has_key?(name)
144
+ # Router and configuration values are nested
145
+ split_config.call(value, local_router[name], keys)
146
+ else
147
+ # Just configuration values are nested
148
+ if local_router.is_a?(String)
149
+ # We are down to a config_name router. Inherit on down the line
150
+ split_config.call(value, local_router, keys)
151
+ else
152
+ # Never encountered before
153
+ config_name = nil
154
+ config_name = select_largest(router.get(parents)) unless parents.empty?
155
+ split_config.call(value, config_name, keys)
156
+ end
157
+ end
158
+ else
159
+ if local_router.is_a?(String)
160
+ # Router is a config_name string
161
+ file_data.set([ local_router, keys ].flatten, value)
162
+ elsif router.is_a?(Hash)
163
+ # Router is a hash with sub options we have to pick from
164
+ config_name = select_largest(local_router)
165
+ file_data.set([ config_name, keys ].flatten, value)
166
+ else
167
+ # Router is non existent
168
+ if config_name = select_largest(router)
169
+ # Pick largest router from top level
170
+ file_data.set([ config_name, keys ].flatten, value)
171
+ else
172
+ # Resort to sane defaults
173
+ default_provider = Manager.connection.type_default(:translator)
174
+ config_name = "corl.#{default_provider}"
175
+ file_data.set([ config_name, keys ].flatten, value)
176
+ end
177
+ end
178
+ end
179
+ end
180
+ end
181
+
182
+ # Whew! Glad that's over...
183
+
184
+ split_config.call(config.export, router.export)
185
+ file_data
186
+ end
187
+ protected :separate
188
+
189
+ #---
190
+
191
+ def save(options = {})
192
+ super do |method_config|
193
+ config_files = []
194
+ success = true
195
+
196
+ separate.export.each do |config_name, router_data|
197
+ info = search[config_name]
198
+ provider = info[:provider]
199
+ file = info[:file]
200
+
201
+ if renderer = CORL.translator(method_config, provider)
202
+ rendering = renderer.generate(router_data)
203
+
204
+ if Util::Disk.write(file, rendering)
205
+ config_files << config_name
206
+ else
207
+ success = false
208
+ end
209
+ else
210
+ success = false
211
+ end
212
+ break unless success
213
+ end
214
+ if success && ! config_files.empty?
215
+ commit_files = [ config_files, method_config.get_array(:files) ].flatten
216
+
217
+ logger.debug("Source configuration rendering: #{rendering}")
218
+ success = update_project(commit_files, method_config)
219
+ end
220
+ success
221
+ end
222
+ end
223
+
224
+ #---
225
+
226
+ def remove(options = {})
227
+ super do |method_config|
228
+ success = true
229
+ config_files = []
230
+ search.each do |config_name, info|
231
+ config_files << info[:file]
232
+ success = false unless Util::Disk.delete(info[:file])
233
+ end
234
+ success = update_project(config_files, method_config) if success
235
+ success
236
+ end
237
+ end
238
+
239
+ #---
240
+
241
+ def attach(type, name, data, options = {})
242
+ super do |method_config|
243
+ attach_path = Util::Disk.filename([ project.directory, type.to_s ])
244
+ success = true
245
+
246
+ begin
247
+ FileUtils.mkdir_p(attach_path) unless Dir.exists?(attach_path)
248
+
249
+ rescue Exception => error
250
+ alert(error.message)
251
+ success = false
252
+ end
253
+
254
+ if success
255
+ case method_config.get(:type, :source)
256
+ when :source
257
+ new_file = project.local_path(Util::Disk.filename([ attach_path, name ]))
258
+
259
+ logger.debug("Attaching source data (length: #{data.length}) to configuration at #{attach_path}")
260
+ success = Util::Disk.write(new_file, data)
261
+
262
+ when :file
263
+ file = ::File.expand_path(data)
264
+ attach_ext = ::File.basename(file)
265
+ new_file = project.local_path(Util::Disk.filename([ attach_path, "#{name}-#{attach_ext}" ]))
266
+
267
+ logger.debug("Attaching file #{file} to configuration at #{attach_path}")
268
+
269
+ begin
270
+ FileUtils.mkdir_p(attach_path) unless Dir.exists?(attach_path)
271
+ FileUtils.cp(file, new_file)
272
+
273
+ rescue Exception => error
274
+ alert(error.message)
275
+ success = false
276
+ end
277
+ end
278
+ end
279
+ if success
280
+ logger.debug("Attaching data to project as #{new_file}")
281
+ success = update_project(new_file, method_config)
282
+ end
283
+ success ? new_file : nil
284
+ end
285
+ end
286
+
287
+ #-----------------------------------------------------------------------------
288
+ # Utilities
289
+
290
+ def search_files
291
+ if Util::Data.empty?(project.directory)
292
+ logger.debug("Clearing configuration file information")
293
+ search.clear
294
+ else
295
+ file_bases = [ "corl", extension_collect(:base) ].flatten
296
+
297
+ Manager.connection.loaded_plugins(:translator).each do |provider, info|
298
+ file_bases.each do |file_base|
299
+ config_name = "#{file_base}.#{provider}"
300
+ file = Util::Disk.filename([ project.directory, config_name ])
301
+
302
+ if Util::Disk.exists?(file)
303
+ search[config_name] = {
304
+ :provider => provider,
305
+ :info => info,
306
+ :file => file
307
+ }
308
+ ObjectSpace.define_finalizer(myself, myself.class.finalize(file))
309
+ else
310
+ logger.info("Configuration file #{file} does not exist")
311
+ end
312
+ end
313
+ end
314
+ logger.debug("Setting configuration file information to #{search.inspect}")
315
+ end
316
+ load(_export) if autoload
317
+ end
318
+ protected :search_files
319
+
320
+ #---
321
+
322
+ def fetch_project(options = {})
323
+ config = Config.ensure(options)
324
+ success = true
325
+ if remote = config.get(:remote, nil)
326
+ logger.info("Pulling configuration updates from remote #{remote}")
327
+ success = project.pull(remote, config) if config.get(:pull, true)
328
+ end
329
+ success
330
+ end
331
+ protected :fetch_project
332
+
333
+ #---
334
+
335
+ def update_project(files = [], options = {})
336
+ config = Config.ensure(options)
337
+ success = true
338
+
339
+ commit_files = '.'
340
+ commit_files = array(files).flatten unless files.empty?
341
+
342
+ logger.info("Committing changes to configuration files")
343
+ success = project.commit(commit_files, config)
344
+
345
+ if success && remote = config.get(:remote, nil)
346
+ logger.info("Pushing configuration updates to remote #{remote}")
347
+ success = project.pull(remote, config) if config.get(:pull, true)
348
+ success = project.push(remote, config) if success && config.get(:push, true)
349
+ end
350
+ success
351
+ end
352
+ protected :update_project
353
+
354
+ #---
355
+
356
+ def select_largest(router)
357
+ config_map = {}
358
+
359
+ count_config_names = lambda do |data|
360
+ data = data.export if data.is_a?(CORL::Config)
361
+ data.each do |name, value|
362
+ if value.is_a?(Hash)
363
+ count_config_names.call(value)
364
+ else
365
+ config_map[value] = 0 unless config_map.has_key?(value)
366
+ config_map[value] = config_map[value] + 1
367
+ end
368
+ end
369
+ end
370
+
371
+ config_name = nil
372
+ config_weight = nil
373
+
374
+ count_config_names.call(router)
375
+ config_map.each do |name, weight|
376
+ if config_name.nil? || weight > config_weight
377
+ config_name = name
378
+ config_weight = weight
379
+ end
380
+ end
381
+ config_name
382
+ end
383
+ protected :select_largest
384
+ end
385
+ end
386
+ end
@@ -0,0 +1,90 @@
1
+
2
+ module CORL
3
+ module Event
4
+ class Puppet < Plugin::Event
5
+
6
+ #-----------------------------------------------------------------------------
7
+ # Puppet event interface
8
+
9
+ def normalize
10
+ super
11
+
12
+ if get(:string)
13
+ items = string(delete(:string)).split(':')
14
+ myself.element = items[0]
15
+ myself.operation = items[1]
16
+ myself.message = items[2]
17
+ end
18
+ end
19
+
20
+ #-----------------------------------------------------------------------------
21
+ # Property accessors / modifiers
22
+
23
+ def element(default = '')
24
+ return get(:element, default, :string)
25
+ end
26
+
27
+ #---
28
+
29
+ def element=element
30
+ set(:element, string(element))
31
+ end
32
+
33
+ #---
34
+
35
+ def operation(default = '')
36
+ return get(:operation, default, :string)
37
+ end
38
+
39
+ #---
40
+
41
+ def operation=operation
42
+ set(:operation, string(operation))
43
+ end
44
+
45
+ #--
46
+
47
+ def message(default = '')
48
+ return get(:message, default, :string)
49
+ end
50
+
51
+ #---
52
+
53
+ def message=message
54
+ set(:message, string(message))
55
+ end
56
+
57
+ #-----------------------------------------------------------------------------
58
+ # Operations
59
+
60
+ def render
61
+ return "#{name}:#{element}:#{operation}:#{message}"
62
+ end
63
+
64
+ #---
65
+
66
+ def check(source)
67
+ if source.match(/notice:\s+(.+?):\s+(.+)\s*/i)
68
+ source_element = $1
69
+ source_operation = ''
70
+ source_message = $2
71
+
72
+ source_elements = source_element.split('/')
73
+ source_operation = source_elements.pop.strip unless source_elements.last.match(/[\[\]]/)
74
+
75
+ if source_operation
76
+ source_element = source_elements.join('/').strip
77
+ success = ( source_element.include?(element) && source_operation == operation && source_message.include?(message) )
78
+
79
+ logger.debug("Checking puppet event with source #{source_element} #{source_operation} #{source_message}: #{success.inspect}")
80
+
81
+ return success
82
+ else
83
+ logger.warn("Can not check puppet event because it is missing an operation")
84
+ end
85
+ end
86
+ return false
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,52 @@
1
+
2
+ module CORL
3
+ module Event
4
+ class Regex < Plugin::Event
5
+
6
+ #-----------------------------------------------------------------------------
7
+ # Regular expression event interface
8
+
9
+ def normalize
10
+ super
11
+
12
+ if get(:string)
13
+ myself.pattern = delete(:string)
14
+ end
15
+ end
16
+
17
+ #-----------------------------------------------------------------------------
18
+ # Property accessors / modifiers
19
+
20
+ def pattern(default = '')
21
+ return get(:pattern, default)
22
+ end
23
+
24
+ #---
25
+
26
+ def pattern=pattern
27
+ set(:pattern, string(pattern))
28
+ end
29
+
30
+ #-----------------------------------------------------------------------------
31
+ # Operations
32
+
33
+ def render
34
+ return "#{name}:#{pattern}"
35
+ end
36
+
37
+ #---
38
+
39
+ def check(source)
40
+ if pattern.empty?
41
+ logger.warn("Can not check regex pattern because it is empty")
42
+ else
43
+ success = source.match(/#{pattern}/)
44
+
45
+ logger.debug("Checking regex event with pattern #{pattern}: #{success.inspect}")
46
+ return success
47
+ end
48
+ return true
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,24 @@
1
+
2
+ module CORL
3
+ module Extension
4
+ class Puppetloader < Plugin::Extension
5
+
6
+ def register_plugins(config)
7
+ connection = Manager.connection
8
+ provisioners = connection.plugins(:provisioner, :puppetnode)
9
+ provisioner = provisioners.empty? ? nil : provisioners[provisioners.keys.first]
10
+
11
+ if provisioner
12
+ # Register Puppet CORL extensions
13
+ provisioner.env.modules.each do |mod|
14
+ lib_dir = File.join(mod.path, 'lib', 'corl')
15
+ if File.directory?(lib_dir)
16
+ logger.debug("Registering Puppet module at #{lib_dir}")
17
+ connection.register(lib_dir)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end