corl 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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