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,407 @@
1
+
2
+ module CORL
3
+ module Provisioner
4
+ class Puppetnode < Plugin::Provisioner
5
+
6
+ #-----------------------------------------------------------------------------
7
+ # Provisioner plugin interface
8
+
9
+ def normalize
10
+ super
11
+
12
+ require 'puppet'
13
+
14
+ if CORL.log_level == :debug
15
+ Puppet.debug = true
16
+ end
17
+ Puppet.initialize_settings
18
+
19
+ myself.plugin_name = :default if plugin_name.to_sym == :puppetnode
20
+
21
+ @env = Puppet::Node::Environment.new
22
+ @compiler = Puppet::Parser::Compiler.new(node)
23
+
24
+ init_scope
25
+ register
26
+ end
27
+
28
+ #---
29
+
30
+ def register
31
+ # Register Puppet CORL extensions
32
+ env.modules.each do |mod|
33
+ lib_dir = File.join(mod.path, 'lib', 'corl')
34
+ if File.directory?(lib_dir)
35
+ logger.debug("Registering Puppet module at #{lib_dir}")
36
+ Manager.connection.register(lib_dir)
37
+ end
38
+ end
39
+ end
40
+
41
+ #-----------------------------------------------------------------------------
42
+ # Property accessor / modifiers
43
+
44
+ def env
45
+ @env
46
+ end
47
+
48
+ #---
49
+
50
+ def compiler
51
+ @compiler
52
+ end
53
+
54
+ #---
55
+
56
+ def init_facts
57
+ facts = {}
58
+
59
+ unless Puppet[:node_name_value].empty?
60
+ facts_obj = Puppet::Node::Facts.indirection.find(Puppet[:node_name_value])
61
+ facts = facts_obj.values if facts_obj
62
+ end
63
+
64
+ set(:facts, facts)
65
+ end
66
+ protected :init_facts
67
+
68
+ #---
69
+
70
+ def facts(reset = false)
71
+ if reset || ! get(:facts)
72
+ init_facts
73
+ end
74
+ get(:facts)
75
+ end
76
+
77
+ #---
78
+
79
+ def init_node
80
+ if name
81
+ name_orig = Puppet[:node_name_value]
82
+ Puppet[:node_name_value] = name
83
+ end
84
+
85
+ node = Puppet::Node.indirection.find(Puppet[:node_name_value])
86
+
87
+ if facts = facts(true)
88
+ node.merge(facts.values)
89
+ end
90
+
91
+ file = Puppet[:classfile]
92
+ if FileTest.exists?(file)
93
+ node.classes = File.read(file).split(/[\s\n]+/)
94
+ end
95
+
96
+ Puppet[:node_name_value] = name_orig if name_orig
97
+ @node = node
98
+ end
99
+ protected :init_node
100
+
101
+ #---
102
+
103
+ def node(reset = false)
104
+ if reset || ! @node
105
+ init_node
106
+ end
107
+ @node
108
+ end
109
+
110
+ #---
111
+
112
+ def init_scope
113
+ @scope = Puppet::Parser::Scope.new(compiler)
114
+ scope.source = Puppet::Resource::Type.new(:node, node.name)
115
+ scope.parent = compiler.topscope
116
+ end
117
+
118
+ #---
119
+
120
+ def scope
121
+ @scope
122
+ end
123
+
124
+ #---
125
+
126
+ def init_catalog
127
+ node = node(true)
128
+
129
+ starttime = Time.now
130
+ catalog = Puppet::Resource::Catalog.indirection.find(node.name, :use_node => node)
131
+
132
+ catalog = catalog.to_ral
133
+ catalog.finalize
134
+
135
+ catalog.retrieval_duration = Time.now - starttime
136
+
137
+ catalog.write_class_file
138
+ catalog.write_resource_file
139
+
140
+ @catalog = catalog
141
+ end
142
+
143
+ #---
144
+
145
+ def catalog(reset = false)
146
+ if reset || ! @catalog
147
+ init_catalog
148
+ end
149
+ @catalog
150
+ end
151
+
152
+ #-----------------------------------------------------------------------------
153
+ # Resources
154
+
155
+ def resource_types
156
+ env.known_resource_types
157
+ end
158
+
159
+ #---
160
+
161
+ def type_info(type_name, reset = false)
162
+ type_name = type_name.to_s.downcase
163
+ type_info = get(:type_info, {})
164
+
165
+ if reset || ! type_info.has_key?(type_name)
166
+ resource_type = nil
167
+ type_exported, type_virtual = false
168
+
169
+ if type_name.start_with?('@@')
170
+ type_name = type_name[2..-1]
171
+ type_exported = true
172
+
173
+ elsif type_name.start_with?('@')
174
+ type_name = type_name[1..-1]
175
+ type_virtual = true
176
+ end
177
+
178
+ if type_name == 'class'
179
+ resource_type = :class
180
+ else
181
+ if resource = Puppet::Type.type(type_name.to_sym)
182
+ resource_type = :type
183
+
184
+ elsif resource = find_definition(type_name)
185
+ resource_type = :define
186
+ end
187
+ end
188
+
189
+ type_info[type_name] = {
190
+ :name => type_name,
191
+ :type => resource_type,
192
+ :resource => resource,
193
+ :exported => type_exported,
194
+ :virtual => type_virtual
195
+ }
196
+ set(:type_info, type_info)
197
+ end
198
+
199
+ type_info[type_name]
200
+ end
201
+
202
+ #---
203
+
204
+ def find_hostclass(name, options = {})
205
+ resource_types.find_hostclass(scope.namespaces, name, options)
206
+ end
207
+
208
+ #---
209
+
210
+ def find_definition(name)
211
+ resource_types.find_definition(scope.namespaces, name)
212
+ end
213
+
214
+ #-----------------------------------------------------------------------------
215
+ # Catalog alterations
216
+
217
+ def clear
218
+ init_catalog
219
+ myself
220
+ end
221
+
222
+ #---
223
+
224
+ def add(type_name, resources, defaults = {}, options = {})
225
+ info = type_info(type_name)
226
+ PuppetExt::ResourceGroup.new(self, info, defaults).add(resources, options)
227
+ end
228
+
229
+ #---
230
+
231
+ def add_resource(type, title, properties)
232
+ if type_name.is_a?(String)
233
+ type = type_info(type)
234
+ end
235
+
236
+ case type[:type]
237
+ when :type, :define
238
+ add_definition(type, title, properties)
239
+ when :class
240
+ add_class(title, properties)
241
+ end
242
+ end
243
+
244
+ #---
245
+
246
+ def add_class(title, properties)
247
+ klass = find_hostclass(title)
248
+ if klass
249
+ klass.ensure_in_catalog(scope, properties)
250
+ catalog.add_class(title)
251
+ end
252
+ end
253
+ protected :add_class
254
+
255
+ #---
256
+
257
+ def add_definition(type, title, properties)
258
+ if type_name.is_a?(String)
259
+ type = type_info(type)
260
+ end
261
+
262
+ resource = Puppet::Parser::Resource.new(type[:name], title, :scope => scope, :source => type[:resource])
263
+ resource.virtual = type[:virtual]
264
+ resource.exported = type[:exported]
265
+
266
+ namevar = namevar(type[:name], title).to_sym
267
+ resource_name = properties.has_key?(namevar) ? properties[namevar] : title
268
+
269
+ { :name => resource_name }.merge(properties).each do |key, value|
270
+ resource.set_parameter(key, value)
271
+ end
272
+ if type[:type] == :define
273
+ type[:resource].instantiate_resource(scope, resource)
274
+ end
275
+ compiler.add_resource(scope, resource)
276
+ end
277
+ protected :add_definition
278
+
279
+ #-----------------------------------------------------------------------------
280
+ # Puppet operations
281
+
282
+ def lookup(property, default = nil, options = {})
283
+ config = Config.ensure(options)
284
+ value = nil
285
+
286
+ puppet_scope = config.get(:puppet_scope, scope)
287
+
288
+ base_names = config.get(:search, nil)
289
+
290
+ search_name = config.get(:search_name, true)
291
+ reverse_lookup = config.get(:reverse_lookup, true)
292
+
293
+ log_level = ::Puppet::Util::Log.level
294
+ Puppet::Util::Log.level = :err # Don't want failed parameter lookup warnings here.
295
+
296
+ if base_names
297
+ if base_names.is_a?(String)
298
+ base_names = [ base_names ]
299
+ end
300
+ base_names = base_names.reverse if reverse_lookup
301
+
302
+ base_names.each do |base|
303
+ value = puppet_scope.lookupvar("::#{base}::#{property}")
304
+ break unless Util::Data.undef?(value)
305
+ end
306
+ end
307
+ if Util::Data.undef?(value) && search_name
308
+ value = puppet_scope.lookupvar("::#{property}")
309
+ end
310
+
311
+ Puppet::Util::Log.level = log_level
312
+ value
313
+ end
314
+
315
+ #--
316
+
317
+ def import(files, base_dir = nil)
318
+ resource_types.loader.import(file, base_dir + '/')
319
+ end
320
+
321
+ #---
322
+
323
+ def include(resource_name, properties, options = {})
324
+ class_data = {}
325
+
326
+ if resource_name.is_a?(Array)
327
+ resource_name = resource_name.flatten
328
+ else
329
+ resource_name = [ resource_name ]
330
+ end
331
+
332
+ resource_name.each do |name|
333
+ classes = lookup(name, [], options)
334
+ if classes.is_a?(Array)
335
+ classes.each do |klass|
336
+ class_data[klass] = parameters
337
+ end
338
+ end
339
+ end
340
+
341
+ klasses = compiler.evaluate_classes(class_data, myself, false)
342
+ missing = class_data.keys.find_all do |klass|
343
+ ! klasses.include?(klass)
344
+ end
345
+
346
+ return false unless missing.empty?
347
+ true
348
+ end
349
+
350
+ #---
351
+
352
+ def provision(options = {})
353
+ config = Config.ensure(options)
354
+
355
+ if ! Util::Data.empty?(config[:code])
356
+ Puppet[:code] = config[:code]
357
+
358
+ elsif ! Util::Data.empty?(config[:manifest])
359
+ Puppet[:manifest] = config[:manifest]
360
+ end
361
+
362
+ begin
363
+ return configure(config[:node])
364
+
365
+ rescue => detail
366
+ Puppet.log_exception(detail)
367
+ end
368
+ false
369
+ end
370
+
371
+ #-----------------------------------------------------------------------------
372
+ # Utilities
373
+
374
+ def to_name(name)
375
+ Util::Data.value(name).to_s.gsub(/[\/\\\-\.]/, '_')
376
+ end
377
+
378
+ #---
379
+
380
+ def type_name(value) # Basically borrowed from Puppet (damn private methods!)
381
+ return :main if value == :main
382
+ return "Class" if value == "" or value.nil? or value.to_s.downcase == "component"
383
+ value.to_s.split("::").collect { |s| s.capitalize }.join("::")
384
+ end
385
+
386
+ #---
387
+
388
+ def namevar(type_name, resource_name) # Basically borrowed from Puppet (damn private methods!)
389
+ resource = Puppet::Resource.new(type_name.sub(/^\@?\@/, ''), resource_name)
390
+
391
+ if resource.builtin_type? and type = resource.resource_type and type.key_attributes.length == 1
392
+ type.key_attributes.first.to_s
393
+ else
394
+ 'name'
395
+ end
396
+ end
397
+
398
+ #---
399
+
400
+ def configure
401
+ configurer = Puppet::Configurer.new
402
+ configurer.run(:catalog => catalog, :pluginsync => false)
403
+ end
404
+ protected :configure
405
+ end
406
+ end
407
+ end
@@ -0,0 +1,73 @@
1
+
2
+ module CORL
3
+ module Template
4
+ class Environment < Plugin::Template
5
+
6
+ #-----------------------------------------------------------------------------
7
+ # Renderers
8
+
9
+ def render_processed(data)
10
+ return super do |output|
11
+ case data
12
+ when Hash
13
+ data.each do |name, value|
14
+ output << render_assignment(name, value)
15
+ end
16
+ end
17
+ output
18
+ end
19
+ end
20
+
21
+ #-----------------------------------------------------------------------------
22
+
23
+ def render_assignment(name, value)
24
+ name = render_name(name)
25
+ value = render_value(value)
26
+
27
+ export = get(:export, true)
28
+ export_text = export ? get(:export_text, 'export ') : ''
29
+ operator = get(:operator, '=')
30
+
31
+ return "#{export_text}#{name}#{operator}#{value}\n"
32
+ end
33
+
34
+ #---
35
+
36
+ def render_name(name)
37
+ prefix = get(:name_prefix, '')
38
+ prefix_sep = prefix.empty? ? '' : get(:name_prefix_sep, '_')
39
+
40
+ suffix = get(:name_suffix, '')
41
+ suffix_sep = suffix.empty? ? '' : get(:name_suffix_sep, '')
42
+
43
+ unless prefix.empty?
44
+ name = "#{prefix}#{prefix_sep}#{name}#{suffix_sep}#{suffix}"
45
+ end
46
+ return name
47
+ end
48
+
49
+ #---
50
+
51
+ def render_value(value)
52
+ sep = get(:value_sep, ' ')
53
+ quote = get(:quote, true)
54
+
55
+ array_prefix = get(:array_prefix, '(')
56
+ array_suffix = get(:array_suffix, ')')
57
+
58
+ case value
59
+ when Array
60
+ values = []
61
+ value.each do |item|
62
+ values << quote ? "'#{item}'" : "#{item}"
63
+ end
64
+ value = "#{array_prefix}#{values.join(sep)}#{array_suffix}"
65
+
66
+ when String
67
+ value = quote ? "'#{value}'" : "#{value}"
68
+ end
69
+ return value
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,16 @@
1
+
2
+ module CORL
3
+ module Template
4
+ class Json < Plugin::Template
5
+
6
+ #-----------------------------------------------------------------------------
7
+ # Renderers
8
+
9
+ def render_processed(data)
10
+ return super do
11
+ Util::Data.to_json(data)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+
2
+ module CORL
3
+ module Template
4
+ class Wrapper < Plugin::Template
5
+
6
+ #-----------------------------------------------------------------------------
7
+ # Renderers
8
+
9
+ def render_processed(data)
10
+ return super do
11
+ get(:template_prefix, '') + data.to_s + get(:template_suffix, '')
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+
2
+ module CORL
3
+ module Template
4
+ class Yaml < Plugin::Template
5
+
6
+ #-----------------------------------------------------------------------------
7
+ # Renderers
8
+
9
+ def render_processed(data)
10
+ return super do
11
+ Util::Data.to_yaml(data)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+
2
+ module CORL
3
+ module Translator
4
+ class Json < Plugin::Translator
5
+
6
+ #-----------------------------------------------------------------------------
7
+ # Translator operations
8
+
9
+ def parse(json_text)
10
+ return super do |properties|
11
+ if json_text && ! json_text.empty?
12
+ properties = Util::Data.parse_json(json_text)
13
+ end
14
+ properties
15
+ end
16
+ end
17
+
18
+ #---
19
+
20
+ def generate(properties)
21
+ return super do
22
+ Util::Data.to_json(properties, get(:pretty, true))
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+
2
+ module CORL
3
+ module Translator
4
+ class Yaml < Plugin::Translator
5
+
6
+ #-----------------------------------------------------------------------------
7
+ # Translator operations
8
+
9
+ def parse(yaml_text)
10
+ return super do |properties|
11
+ if yaml_text && ! yaml_text.empty?
12
+ properties = Util::Data.parse_yaml(yaml_text)
13
+ end
14
+ properties
15
+ end
16
+ end
17
+
18
+ #---
19
+
20
+ def generate(properties)
21
+ return super do
22
+ Util::Data.to_yaml(properties)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end