coral_core 0.2.23 → 0.2.24
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.
- data/.document +5 -0
- data/.gitmodules +12 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +39 -0
- data/Rakefile +79 -0
- data/VERSION +1 -0
- data/coral_core.gemspec +102 -0
- data/lib/coral_core.rb +260 -0
- data/lib/coral_core/command.rb +244 -0
- data/lib/coral_core/config.rb +360 -0
- data/lib/coral_core/core.rb +212 -0
- data/lib/coral_core/event.rb +170 -0
- data/lib/coral_core/event/regexp_event.rb +55 -0
- data/lib/coral_core/interface.rb +180 -0
- data/lib/coral_core/memory.rb +226 -0
- data/lib/coral_core/repository.rb +164 -0
- data/lib/coral_core/resource.rb +243 -0
- data/lib/coral_core/template.rb +92 -0
- data/lib/coral_core/template/environment.rb +72 -0
- data/lib/coral_core/template/json.rb +13 -0
- data/lib/coral_core/template/wrapper.rb +13 -0
- data/lib/coral_core/template/yaml.rb +13 -0
- data/lib/coral_core/util/data.rb +219 -0
- data/lib/coral_core/util/disk.rb +92 -0
- data/lib/coral_core/util/git.rb +15 -0
- data/lib/coral_core/util/git/base.rb +58 -0
- data/lib/coral_core/util/git/lib.rb +82 -0
- data/lib/coral_core/util/git/remote.rb +12 -0
- data/lib/coral_core/util/shell.rb +183 -0
- data/lib/hiera_backend.rb +63 -0
- data/spec/coral_core/interface_spec.rb +489 -0
- data/spec/coral_mock_input.rb +29 -0
- data/spec/coral_test_kernel.rb +22 -0
- data/spec/spec_helper.rb +15 -0
- metadata +38 -4
@@ -0,0 +1,92 @@
|
|
1
|
+
|
2
|
+
module Coral
|
3
|
+
module Template
|
4
|
+
|
5
|
+
#-----------------------------------------------------------------------------
|
6
|
+
# General template utilities
|
7
|
+
|
8
|
+
def self.instance(class_name, options = {}, defaults = {}, force = true)
|
9
|
+
return Template::const_get(class_name).new(options, defaults, force)
|
10
|
+
end
|
11
|
+
|
12
|
+
#---
|
13
|
+
|
14
|
+
def self.process(value)
|
15
|
+
case value
|
16
|
+
when String, Symbol
|
17
|
+
return nil if Util::Data.undef?(value)
|
18
|
+
return 'false' if value == false
|
19
|
+
return 'true' if value == true
|
20
|
+
return value.to_s if value.is_a?(Symbol)
|
21
|
+
|
22
|
+
when Hash
|
23
|
+
results = {}
|
24
|
+
value.each do |key, item|
|
25
|
+
result = process(item)
|
26
|
+
unless result.nil?
|
27
|
+
results[key] = result
|
28
|
+
end
|
29
|
+
value = results
|
30
|
+
end
|
31
|
+
|
32
|
+
when Array
|
33
|
+
results = []
|
34
|
+
value.each_with_index do |item, index|
|
35
|
+
result = process(item)
|
36
|
+
unless result.nil?
|
37
|
+
results << result
|
38
|
+
end
|
39
|
+
end
|
40
|
+
value = results
|
41
|
+
end
|
42
|
+
return value
|
43
|
+
end
|
44
|
+
|
45
|
+
#---
|
46
|
+
|
47
|
+
def self.render(class_name, data, options = {})
|
48
|
+
config = Config.ensure(options)
|
49
|
+
|
50
|
+
normalize = config.get(:normalize_template, true)
|
51
|
+
interpolate = config.get(:interpolate_template, true)
|
52
|
+
|
53
|
+
#dbg(class_name, 'template engine name')
|
54
|
+
#dbg(data, 'template data -> init')
|
55
|
+
|
56
|
+
if normalize
|
57
|
+
data = Config.normalize(data, nil, config)
|
58
|
+
#dbg(data, 'template data -> post normalization')
|
59
|
+
end
|
60
|
+
|
61
|
+
if normalize && interpolate
|
62
|
+
data = Util::Data.interpolate(data, data, config.options)
|
63
|
+
#dbg(data, 'template data -> post interpolation')
|
64
|
+
end
|
65
|
+
|
66
|
+
engine = instance(class_name, config, {}, config.get(:force, true))
|
67
|
+
#dbg(engine, 'template engine')
|
68
|
+
|
69
|
+
output = engine.render(process(data))
|
70
|
+
#dbg(output, 'template output')
|
71
|
+
|
72
|
+
return output
|
73
|
+
end
|
74
|
+
|
75
|
+
#-----------------------------------------------------------------------------
|
76
|
+
# Base template
|
77
|
+
|
78
|
+
class Base < Config
|
79
|
+
# All template classes should extend Base
|
80
|
+
|
81
|
+
def intialize(options = {}, defaults = {}, force = true)
|
82
|
+
super(options, defaults, force)
|
83
|
+
end
|
84
|
+
|
85
|
+
#---
|
86
|
+
|
87
|
+
def render(input)
|
88
|
+
return '' # Implement in sub classes!!
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
|
2
|
+
module Coral
|
3
|
+
module Template
|
4
|
+
class Environment < Base
|
5
|
+
#-----------------------------------------------------------------------------
|
6
|
+
# Renderers
|
7
|
+
|
8
|
+
def render(input)
|
9
|
+
output = ''
|
10
|
+
|
11
|
+
case input
|
12
|
+
when Hash
|
13
|
+
input.each do |name, value|
|
14
|
+
output << render_assignment(name, value)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
return output
|
18
|
+
end
|
19
|
+
|
20
|
+
#-----------------------------------------------------------------------------
|
21
|
+
|
22
|
+
def render_assignment(name, value)
|
23
|
+
name = render_name(name)
|
24
|
+
value = render_value(value)
|
25
|
+
|
26
|
+
export = get(:export, true)
|
27
|
+
export_text = export ? get(:export_text, 'export ') : ''
|
28
|
+
operator = get(:operator, '=')
|
29
|
+
|
30
|
+
return "#{export_text}#{name}#{operator}#{value}\n"
|
31
|
+
end
|
32
|
+
|
33
|
+
#---
|
34
|
+
|
35
|
+
def render_name(name)
|
36
|
+
prefix = get(:name_prefix, '')
|
37
|
+
prefix_sep = prefix.empty? ? '' : get(:name_prefix_sep, '_')
|
38
|
+
|
39
|
+
suffix = get(:name_suffix, '')
|
40
|
+
suffix_sep = suffix.empty? ? '' : get(:name_suffix_sep, '')
|
41
|
+
|
42
|
+
unless prefix.empty?
|
43
|
+
name = "#{prefix}#{prefix_sep}#{name}#{suffix_sep}#{suffix}"
|
44
|
+
end
|
45
|
+
return name
|
46
|
+
end
|
47
|
+
|
48
|
+
#---
|
49
|
+
|
50
|
+
def render_value(value)
|
51
|
+
sep = get(:value_sep, ' ')
|
52
|
+
quote = get(:quote, true)
|
53
|
+
|
54
|
+
array_prefix = get(:array_prefix, '(')
|
55
|
+
array_suffix = get(:array_suffix, ')')
|
56
|
+
|
57
|
+
case value
|
58
|
+
when Array
|
59
|
+
values = []
|
60
|
+
value.each do |item|
|
61
|
+
values << quote ? "'#{item}'" : "#{item}"
|
62
|
+
end
|
63
|
+
value = "#{array_prefix}#{values.join(sep)}#{array_suffix}"
|
64
|
+
|
65
|
+
when String
|
66
|
+
value = quote ? "'#{value}'" : "#{value}"
|
67
|
+
end
|
68
|
+
return value
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
|
2
|
+
module Coral
|
3
|
+
module Template
|
4
|
+
class Wrapper < Base
|
5
|
+
#-----------------------------------------------------------------------------
|
6
|
+
# Renderers
|
7
|
+
|
8
|
+
def render(input)
|
9
|
+
return get(:template_prefix, '') + input.to_s + get(:template_suffix, '')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,219 @@
|
|
1
|
+
|
2
|
+
module Coral
|
3
|
+
module Util
|
4
|
+
class Data
|
5
|
+
|
6
|
+
#-----------------------------------------------------------------------------
|
7
|
+
# Type checking
|
8
|
+
|
9
|
+
def self.undef?(value)
|
10
|
+
if value.nil? ||
|
11
|
+
(value.is_a?(Symbol) && value == :undef || value == :undefined) ||
|
12
|
+
(value.is_a?(String) && value.match(/^\s*(undef|UNDEF|Undef|nil|NIL|Nil)\s*$/))
|
13
|
+
return true
|
14
|
+
end
|
15
|
+
return false
|
16
|
+
end
|
17
|
+
|
18
|
+
#---
|
19
|
+
|
20
|
+
def self.true?(value)
|
21
|
+
if value == true ||
|
22
|
+
(value.is_a?(String) && value.match(/^\s*(true|TRUE|True)\s*$/))
|
23
|
+
return true
|
24
|
+
end
|
25
|
+
return false
|
26
|
+
end
|
27
|
+
|
28
|
+
#---
|
29
|
+
|
30
|
+
def self.false?(value)
|
31
|
+
if value == false ||
|
32
|
+
(value.is_a?(String) && value.match(/^\s*(false|FALSE|False)\s*$/))
|
33
|
+
return true
|
34
|
+
end
|
35
|
+
return false
|
36
|
+
end
|
37
|
+
|
38
|
+
#---
|
39
|
+
|
40
|
+
def self.empty?(value)
|
41
|
+
if undef?(value) || false?(value) || (value.respond_to?('empty?') && value.empty?)
|
42
|
+
return true
|
43
|
+
end
|
44
|
+
return false
|
45
|
+
end
|
46
|
+
|
47
|
+
#-----------------------------------------------------------------------------
|
48
|
+
# Translation
|
49
|
+
|
50
|
+
def self.to_json(data)
|
51
|
+
output = ''
|
52
|
+
begin
|
53
|
+
output = data.to_json
|
54
|
+
|
55
|
+
rescue Exception
|
56
|
+
end
|
57
|
+
return output
|
58
|
+
end
|
59
|
+
|
60
|
+
#---
|
61
|
+
|
62
|
+
def self.to_yaml(data)
|
63
|
+
output = ''
|
64
|
+
begin
|
65
|
+
require 'yaml'
|
66
|
+
output = YAML.dump(data)
|
67
|
+
|
68
|
+
rescue Exception
|
69
|
+
end
|
70
|
+
return output
|
71
|
+
end
|
72
|
+
|
73
|
+
#---
|
74
|
+
|
75
|
+
def self.value(value)
|
76
|
+
case value
|
77
|
+
when String
|
78
|
+
if undef?(value)
|
79
|
+
value = nil
|
80
|
+
elsif true?(value)
|
81
|
+
value = true
|
82
|
+
elsif false?(value)
|
83
|
+
value = false
|
84
|
+
end
|
85
|
+
|
86
|
+
when Array
|
87
|
+
value.each_with_index do |item, index|
|
88
|
+
value[index] = value(item)
|
89
|
+
end
|
90
|
+
|
91
|
+
when Hash
|
92
|
+
value.each do |key, data|
|
93
|
+
value[key] = value(data)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
return value
|
97
|
+
end
|
98
|
+
|
99
|
+
#-----------------------------------------------------------------------------
|
100
|
+
# Operations
|
101
|
+
|
102
|
+
def self.merge(data, force = true)
|
103
|
+
value = data
|
104
|
+
|
105
|
+
# Special case because this method is called from within Config.new so we
|
106
|
+
# can not use Config.ensure, as that would cause an infinite loop.
|
107
|
+
force = force.is_a?(Coral::Config) ? force.get(:force, true) : force
|
108
|
+
|
109
|
+
if data.is_a?(Array)
|
110
|
+
value = data.shift.clone
|
111
|
+
|
112
|
+
data.each do |item|
|
113
|
+
item = item.clone
|
114
|
+
|
115
|
+
case value
|
116
|
+
when Hash
|
117
|
+
begin
|
118
|
+
require 'deep_merge'
|
119
|
+
value = force ? value.deep_merge!(item) : value.deep_merge(item)
|
120
|
+
|
121
|
+
rescue LoadError
|
122
|
+
if item.is_a?(Hash) # Non recursive top level by default.
|
123
|
+
value = value.merge(item)
|
124
|
+
elsif force
|
125
|
+
value = item
|
126
|
+
end
|
127
|
+
end
|
128
|
+
when Array
|
129
|
+
if item.is_a?(Array)
|
130
|
+
value = value.concat(item).uniq
|
131
|
+
elsif force
|
132
|
+
value = item
|
133
|
+
end
|
134
|
+
|
135
|
+
when String, Symbol
|
136
|
+
value = item if item.is_a?(String) || item.is_a?(Symbol) || force
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
return value
|
142
|
+
end
|
143
|
+
|
144
|
+
#---
|
145
|
+
|
146
|
+
def self.interpolate(value, scope, options = {})
|
147
|
+
|
148
|
+
pattern = ( options.has_key?(:pattern) ? options[:pattern] : '\$(\{)?([a-zA-Z0-9\_\-]+)(\})?' )
|
149
|
+
group = ( options.has_key?(:var_group) ? options[:var_group] : 2 )
|
150
|
+
flags = ( options.has_key?(:flags) ? options[:flags] : '' )
|
151
|
+
|
152
|
+
if scope.is_a?(Hash)
|
153
|
+
regexp = Regexp.new(pattern, flags.split(''))
|
154
|
+
|
155
|
+
replace = lambda do |item|
|
156
|
+
matches = item.match(regexp)
|
157
|
+
result = nil
|
158
|
+
|
159
|
+
#dbg(item, 'item')
|
160
|
+
#dbg(matches, 'matches')
|
161
|
+
|
162
|
+
unless matches.nil?
|
163
|
+
replacement = scope.search(matches[group], options)
|
164
|
+
result = item.gsub(matches[0], replacement) unless replacement.nil?
|
165
|
+
end
|
166
|
+
return result
|
167
|
+
end
|
168
|
+
|
169
|
+
case value
|
170
|
+
when String
|
171
|
+
#dbg(value, 'interpolate (string) -> init')
|
172
|
+
while (temp = replace.call(value))
|
173
|
+
#dbg(temp, 'interpolate (string) -> replacement')
|
174
|
+
value = temp
|
175
|
+
end
|
176
|
+
|
177
|
+
when Hash
|
178
|
+
#dbg(value, 'interpolate (hash) -> init')
|
179
|
+
value.each do |key, data|
|
180
|
+
#dbg(data, "interpolate (#{key}) -> data")
|
181
|
+
value[key] = interpolate(data, scope, options)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
#dbg(value, 'interpolate -> result')
|
186
|
+
return value
|
187
|
+
end
|
188
|
+
|
189
|
+
#-----------------------------------------------------------------------------
|
190
|
+
# Utilities
|
191
|
+
|
192
|
+
def self.prefix(prefix, data)
|
193
|
+
result = nil
|
194
|
+
|
195
|
+
unless prefix.is_a?(String) && ! empty?(prefix)
|
196
|
+
prefix = ''
|
197
|
+
end
|
198
|
+
|
199
|
+
case data
|
200
|
+
when String, Symbol
|
201
|
+
result = ( prefix.empty? ? data.to_s : prefix + '_' + data.to_s )
|
202
|
+
|
203
|
+
when Array
|
204
|
+
result = []
|
205
|
+
data.each do |value|
|
206
|
+
result << prefix(prefix, value)
|
207
|
+
end
|
208
|
+
|
209
|
+
when Hash
|
210
|
+
result = {}
|
211
|
+
data.each do |key, value|
|
212
|
+
result[prefix(prefix, key)] = value
|
213
|
+
end
|
214
|
+
end
|
215
|
+
return result
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
|
2
|
+
module Coral
|
3
|
+
module Util
|
4
|
+
class Disk
|
5
|
+
|
6
|
+
#-----------------------------------------------------------------------------
|
7
|
+
# Properties
|
8
|
+
|
9
|
+
@@files = {}
|
10
|
+
|
11
|
+
@@separator = false
|
12
|
+
@@description = ''
|
13
|
+
|
14
|
+
#-----------------------------------------------------------------------------
|
15
|
+
# Utilities
|
16
|
+
|
17
|
+
def self.open(file_name, options = {}, reset = false)
|
18
|
+
mode = options[:mode].to_s
|
19
|
+
|
20
|
+
@@separator = ( options[:separator] ? options[:separator] : false )
|
21
|
+
@@description = ( options[:description] ? options[:description] : '' )
|
22
|
+
|
23
|
+
if @@files.has_key?(file_name) && ! reset
|
24
|
+
reset = true if ! mode.empty? && mode != @@files[file_name][:mode]
|
25
|
+
end
|
26
|
+
|
27
|
+
if ! @@files.has_key?(file_name) || ! @@files[file_name][:file] || reset
|
28
|
+
@@files[file_name][:file].close if @@files[file_name] && @@files[file_name][:file]
|
29
|
+
unless mode.empty? || ( mode == 'r' && ! File.exists?(file_name) )
|
30
|
+
@@files[file_name] = {
|
31
|
+
:file => File.open(file_name, mode),
|
32
|
+
:mode => mode,
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
return nil unless @@files[file_name]
|
37
|
+
return @@files[file_name][:file]
|
38
|
+
end
|
39
|
+
|
40
|
+
#---
|
41
|
+
|
42
|
+
def self.read(file_name, options = {})
|
43
|
+
options[:mode] = ( options[:mode] ? options[:mode] : 'r' )
|
44
|
+
file = open(file_name, options)
|
45
|
+
|
46
|
+
if file
|
47
|
+
return file.read
|
48
|
+
end
|
49
|
+
return nil
|
50
|
+
end
|
51
|
+
|
52
|
+
#---
|
53
|
+
|
54
|
+
def self.write(file_name, data, options = {})
|
55
|
+
options[:mode] = ( options[:mode] ? options[:mode] : 'w' )
|
56
|
+
file = open(file_name, options)
|
57
|
+
|
58
|
+
if file
|
59
|
+
return file.write(data)
|
60
|
+
end
|
61
|
+
return nil
|
62
|
+
end
|
63
|
+
|
64
|
+
#---
|
65
|
+
|
66
|
+
def self.log(data, options = {})
|
67
|
+
reset = ( options[:file_name] || options[:mode] )
|
68
|
+
file = open(( options[:file_name] ? options[:file_name] : 'log.txt' ), options, reset)
|
69
|
+
if file
|
70
|
+
file.write("--------------------------------------\n") if @@separator
|
71
|
+
file.write("#{@@description}\n") if @@description
|
72
|
+
file.write("#{data}\n")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
#---
|
77
|
+
|
78
|
+
def self.close(file_names = [])
|
79
|
+
file_names = @@files.keys unless file_names && ! file_names.empty?
|
80
|
+
|
81
|
+
unless file_names.is_a?(Array)
|
82
|
+
file_names = [ file_names ]
|
83
|
+
end
|
84
|
+
|
85
|
+
file_names.each do |file_name|
|
86
|
+
@@files[file_name][:file].close if @@files[file_name] && @@files[file_name][:file]
|
87
|
+
@@files.delete(file_name)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|