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