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,212 @@
|
|
1
|
+
|
2
|
+
module Coral
|
3
|
+
class Core
|
4
|
+
|
5
|
+
#-----------------------------------------------------------------------------
|
6
|
+
# Properties
|
7
|
+
|
8
|
+
@@ui = Interface.new("coral")
|
9
|
+
|
10
|
+
#-----------------------------------------------------------------------------
|
11
|
+
# Constructor / Destructor
|
12
|
+
|
13
|
+
def initialize(options = {})
|
14
|
+
config = Config.ensure(options)
|
15
|
+
|
16
|
+
@ui = Interface.new(config)
|
17
|
+
end
|
18
|
+
|
19
|
+
#-----------------------------------------------------------------------------
|
20
|
+
# Accessor / Modifiers
|
21
|
+
|
22
|
+
attr_accessor :ui
|
23
|
+
|
24
|
+
#-----------------------------------------------------------------------------
|
25
|
+
|
26
|
+
def self.ui
|
27
|
+
return @@ui
|
28
|
+
end
|
29
|
+
|
30
|
+
#---
|
31
|
+
|
32
|
+
def self.logger
|
33
|
+
return @@ui.logger
|
34
|
+
end
|
35
|
+
|
36
|
+
#---
|
37
|
+
|
38
|
+
def logger
|
39
|
+
return self.class.logger
|
40
|
+
end
|
41
|
+
|
42
|
+
#---
|
43
|
+
|
44
|
+
def logger=logger
|
45
|
+
self.class.logger = logger
|
46
|
+
end
|
47
|
+
|
48
|
+
#-----------------------------------------------------------------------------
|
49
|
+
# General utilities
|
50
|
+
|
51
|
+
def self.symbol_map(data)
|
52
|
+
results = {}
|
53
|
+
return data unless data
|
54
|
+
|
55
|
+
case data
|
56
|
+
when Hash
|
57
|
+
data.each do |key, value|
|
58
|
+
results[key.to_sym] = symbol_map(value)
|
59
|
+
end
|
60
|
+
else
|
61
|
+
results = data
|
62
|
+
end
|
63
|
+
return results
|
64
|
+
end
|
65
|
+
|
66
|
+
#---
|
67
|
+
|
68
|
+
def symbol_map(data)
|
69
|
+
return self.class.symbol_map(data)
|
70
|
+
end
|
71
|
+
|
72
|
+
#---
|
73
|
+
|
74
|
+
def self.string_map(data)
|
75
|
+
results = {}
|
76
|
+
return data unless data
|
77
|
+
|
78
|
+
case data
|
79
|
+
when Hash
|
80
|
+
data.each do |key, value|
|
81
|
+
results[key.to_s] = string_map(value)
|
82
|
+
end
|
83
|
+
else
|
84
|
+
results = data
|
85
|
+
end
|
86
|
+
return results
|
87
|
+
end
|
88
|
+
|
89
|
+
#---
|
90
|
+
|
91
|
+
def string_map(data)
|
92
|
+
return self.class.string_map(data)
|
93
|
+
end
|
94
|
+
|
95
|
+
#-----------------------------------------------------------------------------
|
96
|
+
|
97
|
+
def self.filter(data, method = false)
|
98
|
+
if method && method.is_a?(Symbol) &&
|
99
|
+
[ :array, :hash, :string, :symbol, :test ].include?(method.to_sym)
|
100
|
+
return send(method, data)
|
101
|
+
end
|
102
|
+
return data
|
103
|
+
end
|
104
|
+
|
105
|
+
#---
|
106
|
+
|
107
|
+
def filter(data, method = false)
|
108
|
+
return self.class.filter(data, method)
|
109
|
+
end
|
110
|
+
|
111
|
+
#-----------------------------------------------------------------------------
|
112
|
+
|
113
|
+
def self.array(data, default = [], split_string = false)
|
114
|
+
result = default
|
115
|
+
if data
|
116
|
+
case data
|
117
|
+
when Array
|
118
|
+
result = data
|
119
|
+
when String
|
120
|
+
result = [ ( split_string ? data.split(/\s*,\s*/) : data ) ]
|
121
|
+
else
|
122
|
+
result = [ data ]
|
123
|
+
end
|
124
|
+
end
|
125
|
+
return result
|
126
|
+
end
|
127
|
+
|
128
|
+
#---
|
129
|
+
|
130
|
+
def array(data, default = [], split_string = false)
|
131
|
+
return self.class.array(data, default, split_string)
|
132
|
+
end
|
133
|
+
|
134
|
+
#---
|
135
|
+
|
136
|
+
def self.hash(data, default = {})
|
137
|
+
result = default
|
138
|
+
if data
|
139
|
+
case data
|
140
|
+
when Hash
|
141
|
+
result = data
|
142
|
+
else
|
143
|
+
result = {}
|
144
|
+
end
|
145
|
+
end
|
146
|
+
return result
|
147
|
+
end
|
148
|
+
|
149
|
+
#---
|
150
|
+
|
151
|
+
def hash(data, default = {})
|
152
|
+
return self.class.hash(data, default)
|
153
|
+
end
|
154
|
+
|
155
|
+
#---
|
156
|
+
|
157
|
+
def self.string(data, default = '')
|
158
|
+
result = default
|
159
|
+
if data
|
160
|
+
case data
|
161
|
+
when String
|
162
|
+
result = data
|
163
|
+
else
|
164
|
+
result = data.to_s
|
165
|
+
end
|
166
|
+
end
|
167
|
+
return result
|
168
|
+
end
|
169
|
+
|
170
|
+
#---
|
171
|
+
|
172
|
+
def string(data, default = '')
|
173
|
+
return self.class.string(data, default)
|
174
|
+
end
|
175
|
+
|
176
|
+
#---
|
177
|
+
|
178
|
+
def self.symbol(data, default = :undefined)
|
179
|
+
result = default
|
180
|
+
if data
|
181
|
+
case data
|
182
|
+
when Symbol
|
183
|
+
result = data
|
184
|
+
when String
|
185
|
+
result = data.to_sym
|
186
|
+
else
|
187
|
+
result = data.class.to_sym
|
188
|
+
end
|
189
|
+
end
|
190
|
+
return result
|
191
|
+
end
|
192
|
+
|
193
|
+
#---
|
194
|
+
|
195
|
+
def symbol(data, default = '')
|
196
|
+
return self.class.symbol(data, default)
|
197
|
+
end
|
198
|
+
|
199
|
+
#---
|
200
|
+
|
201
|
+
def self.test(data)
|
202
|
+
return false if Util::Data.empty?(data)
|
203
|
+
return true
|
204
|
+
end
|
205
|
+
|
206
|
+
#---
|
207
|
+
|
208
|
+
def test(data)
|
209
|
+
return self.class.test(data)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
|
2
|
+
module Coral
|
3
|
+
class Event < Core
|
4
|
+
|
5
|
+
#-----------------------------------------------------------------------------
|
6
|
+
# Constructor / Destructor
|
7
|
+
|
8
|
+
def self.instance!(data = {}, build_hash = false, keep_array = false)
|
9
|
+
group = ( build_hash ? {} : [] )
|
10
|
+
events = build_info(data)
|
11
|
+
|
12
|
+
index = 1
|
13
|
+
events.each do |info|
|
14
|
+
type = info[:type]
|
15
|
+
|
16
|
+
if type && ! type.empty?
|
17
|
+
event = ( block_given? ? yield(type, info) : create(type, info) )
|
18
|
+
|
19
|
+
if event
|
20
|
+
if build_hash
|
21
|
+
group[index] = event
|
22
|
+
else
|
23
|
+
group << event
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
index += 1
|
28
|
+
end
|
29
|
+
if ! build_hash && events.length == 1 && ! keep_array
|
30
|
+
return group.shift
|
31
|
+
end
|
32
|
+
return group
|
33
|
+
end
|
34
|
+
|
35
|
+
#---
|
36
|
+
|
37
|
+
def self.instance(options = {}, build_hash = false, keep_array = false)
|
38
|
+
return instance!(options, build_hash, keep_array)
|
39
|
+
end
|
40
|
+
|
41
|
+
#---
|
42
|
+
|
43
|
+
def initialize(options = {})
|
44
|
+
config = Config.ensure(options)
|
45
|
+
|
46
|
+
super(config)
|
47
|
+
|
48
|
+
@name = config.get(:name, '')
|
49
|
+
@delegate = config.get(:delegate, nil)
|
50
|
+
@properties = config.options
|
51
|
+
end
|
52
|
+
|
53
|
+
#-----------------------------------------------------------------------------
|
54
|
+
# Property accessors / modifiers
|
55
|
+
|
56
|
+
attr_accessor :name
|
57
|
+
|
58
|
+
#---
|
59
|
+
|
60
|
+
def type
|
61
|
+
return string(@properties[:type])
|
62
|
+
end
|
63
|
+
|
64
|
+
#---
|
65
|
+
|
66
|
+
def set_properties(data)
|
67
|
+
return @delegate.set_properties(data) if @delegate
|
68
|
+
|
69
|
+
@properties = hash(data)
|
70
|
+
return self
|
71
|
+
end
|
72
|
+
|
73
|
+
#---
|
74
|
+
|
75
|
+
def property(name, default = '', format = false)
|
76
|
+
name = name.to_sym
|
77
|
+
|
78
|
+
property = default
|
79
|
+
property = filter(@properties[name], format) if @properties.has_key?(name)
|
80
|
+
return property
|
81
|
+
end
|
82
|
+
|
83
|
+
#---
|
84
|
+
|
85
|
+
def set_property(name, value)
|
86
|
+
return @delegate.set_property(name, value) if @delegate
|
87
|
+
|
88
|
+
@properties[name] = value
|
89
|
+
return self
|
90
|
+
end
|
91
|
+
|
92
|
+
#-----------------------------------------------------------------------------
|
93
|
+
# Import / Export
|
94
|
+
|
95
|
+
def export
|
96
|
+
return type
|
97
|
+
end
|
98
|
+
|
99
|
+
#-----------------------------------------------------------------------------
|
100
|
+
# Event handling
|
101
|
+
|
102
|
+
def check(source)
|
103
|
+
return false
|
104
|
+
end
|
105
|
+
|
106
|
+
#-----------------------------------------------------------------------------
|
107
|
+
# Utilities
|
108
|
+
|
109
|
+
def self.build_info!(data = {})
|
110
|
+
events = []
|
111
|
+
|
112
|
+
if data.is_a?(String)
|
113
|
+
data = data.split(/\s*,\s*/)
|
114
|
+
elsif data.is_a?(Hash)
|
115
|
+
data = [ data ]
|
116
|
+
end
|
117
|
+
|
118
|
+
if data.is_a?(Array)
|
119
|
+
data.each do |element|
|
120
|
+
event = {}
|
121
|
+
|
122
|
+
if block_given?
|
123
|
+
event = yield(element)
|
124
|
+
else
|
125
|
+
case element
|
126
|
+
when String
|
127
|
+
event = split_event_string(element)
|
128
|
+
|
129
|
+
when Hash
|
130
|
+
event = element
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
unless event.empty?
|
135
|
+
events << event
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
return events
|
140
|
+
end
|
141
|
+
|
142
|
+
#---
|
143
|
+
|
144
|
+
def self.build_info(data = {})
|
145
|
+
return build_info!(data)
|
146
|
+
end
|
147
|
+
|
148
|
+
#-----------------------------------------------------------------------------
|
149
|
+
|
150
|
+
def self.create(type, info)
|
151
|
+
event = nil
|
152
|
+
begin
|
153
|
+
event = Module.const_get("Coral").const_get("#{type.capitalize}Event").new(info)
|
154
|
+
rescue
|
155
|
+
end
|
156
|
+
return event
|
157
|
+
end
|
158
|
+
|
159
|
+
#-----------------------------------------------------------------------------
|
160
|
+
|
161
|
+
def self.split_event_string(data)
|
162
|
+
info = {}
|
163
|
+
components = data.split(':')
|
164
|
+
info[:type] = components.shift
|
165
|
+
info[:string] = components.join(':')
|
166
|
+
|
167
|
+
return info
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
|
2
|
+
module Coral
|
3
|
+
class RegexpEvent < Event
|
4
|
+
|
5
|
+
#-----------------------------------------------------------------------------
|
6
|
+
# Properties
|
7
|
+
|
8
|
+
TYPE = :regexp
|
9
|
+
|
10
|
+
#-----------------------------------------------------------------------------
|
11
|
+
# Constructor / Destructor
|
12
|
+
|
13
|
+
def initialize(options = {})
|
14
|
+
options[:type] = TYPE
|
15
|
+
|
16
|
+
super(options)
|
17
|
+
|
18
|
+
if options.has_key?(:string)
|
19
|
+
self.pattern = options[:string]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
#-----------------------------------------------------------------------------
|
24
|
+
# Property accessors / modifiers
|
25
|
+
|
26
|
+
def pattern
|
27
|
+
return property(:pattern, '', :string)
|
28
|
+
end
|
29
|
+
|
30
|
+
#---
|
31
|
+
|
32
|
+
def pattern=pattern
|
33
|
+
set_property(:pattern, string(pattern))
|
34
|
+
end
|
35
|
+
|
36
|
+
#-----------------------------------------------------------------------------
|
37
|
+
# Import / Export
|
38
|
+
|
39
|
+
def export
|
40
|
+
return "#{type}:#{pattern}"
|
41
|
+
end
|
42
|
+
|
43
|
+
#-----------------------------------------------------------------------------
|
44
|
+
# Event handling
|
45
|
+
|
46
|
+
def check(source)
|
47
|
+
if source.match(/#{pattern}/)
|
48
|
+
logger.debug("MATCH! -> #{pattern} matched #{source}")
|
49
|
+
return true
|
50
|
+
end
|
51
|
+
logger.debug("nothing -> #{pattern} - #{source}")
|
52
|
+
return false
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
|
2
|
+
require 'log4r'
|
3
|
+
|
4
|
+
module Coral
|
5
|
+
class Interface
|
6
|
+
|
7
|
+
#-----------------------------------------------------------------------------
|
8
|
+
# Properties
|
9
|
+
|
10
|
+
@@logger = Log4r::Logger.new("coral::interface")
|
11
|
+
|
12
|
+
#---
|
13
|
+
|
14
|
+
COLORS = {
|
15
|
+
:clear => "\e[0m",
|
16
|
+
:red => "\e[31m",
|
17
|
+
:green => "\e[32m",
|
18
|
+
:yellow => "\e[33m"
|
19
|
+
}
|
20
|
+
|
21
|
+
COLOR_MAP = {
|
22
|
+
:warn => COLORS[:yellow],
|
23
|
+
:error => COLORS[:red],
|
24
|
+
:success => COLORS[:green]
|
25
|
+
}
|
26
|
+
|
27
|
+
#-----------------------------------------------------------------------------
|
28
|
+
# Constructor
|
29
|
+
|
30
|
+
def initialize(options = {})
|
31
|
+
class_name = self.class.to_s.downcase
|
32
|
+
|
33
|
+
if options.is_a?(String)
|
34
|
+
options = { :resource => options, :logger => options }
|
35
|
+
end
|
36
|
+
config = Config.ensure(options)
|
37
|
+
|
38
|
+
if config.get(:logger, false)
|
39
|
+
if config[:logger].is_a?(String)
|
40
|
+
@logger = Log4r::Logger.new(config[:logger])
|
41
|
+
else
|
42
|
+
@logger = config[:logger]
|
43
|
+
end
|
44
|
+
else
|
45
|
+
@logger = Log4r::Logger.new(class_name)
|
46
|
+
end
|
47
|
+
|
48
|
+
@resource = config.get(:resource, '')
|
49
|
+
@color = config.get(:color, true)
|
50
|
+
|
51
|
+
@printer = config.get(:printer, :puts)
|
52
|
+
|
53
|
+
@input = config.get(:input, $stdin)
|
54
|
+
@output = config.get(:output, $stdout)
|
55
|
+
@error = config.get(:error, $stderr)
|
56
|
+
|
57
|
+
@delegate = config.get(:ui_delegate, nil)
|
58
|
+
end
|
59
|
+
|
60
|
+
#-----------------------------------------------------------------------------
|
61
|
+
# Accessors / Modifiers
|
62
|
+
|
63
|
+
attr_accessor :logger, :resource, :color, :input, :output, :error, :delegate
|
64
|
+
|
65
|
+
#-----------------------------------------------------------------------------
|
66
|
+
|
67
|
+
def self.logger
|
68
|
+
return @@logger
|
69
|
+
end
|
70
|
+
|
71
|
+
#-----------------------------------------------------------------------------
|
72
|
+
# UI functionality
|
73
|
+
|
74
|
+
def say(type, message, options = {})
|
75
|
+
return @delegate.say(type, message, options) if check_delegate('say')
|
76
|
+
|
77
|
+
defaults = { :new_line => true, :prefix => true }
|
78
|
+
options = defaults.merge(options)
|
79
|
+
printer = options[:new_line] ? :puts : :print
|
80
|
+
channel = type == :error || options[:channel] == :error ? @error : @output
|
81
|
+
|
82
|
+
safe_puts(format_message(type, message, options),
|
83
|
+
:channel => channel, :printer => printer)
|
84
|
+
end
|
85
|
+
|
86
|
+
#---
|
87
|
+
|
88
|
+
def ask(message, options = {})
|
89
|
+
return @delegate.ask(message, options) if check_delegate('ask')
|
90
|
+
|
91
|
+
options[:new_line] = false if ! options.has_key?(:new_line)
|
92
|
+
options[:prefix] = false if ! options.has_key?(:prefix)
|
93
|
+
|
94
|
+
say(:info, message, options)
|
95
|
+
return @input.gets.chomp
|
96
|
+
end
|
97
|
+
|
98
|
+
#-----------------------------------------------------------------------------
|
99
|
+
|
100
|
+
def info(message, *args)
|
101
|
+
@logger.info("info: #{message}")
|
102
|
+
|
103
|
+
return @delegate.info(message, *args) if check_delegate('info')
|
104
|
+
say(:info, message, *args)
|
105
|
+
end
|
106
|
+
|
107
|
+
#---
|
108
|
+
|
109
|
+
def warn(message, *args)
|
110
|
+
@logger.info("warn: #{message}")
|
111
|
+
|
112
|
+
return @delegate.warn(message, *args) if check_delegate('warn')
|
113
|
+
say(:warn, message, *args)
|
114
|
+
end
|
115
|
+
|
116
|
+
#---
|
117
|
+
|
118
|
+
def error(message, *args)
|
119
|
+
@logger.info("error: #{message}")
|
120
|
+
|
121
|
+
return @delegate.error(message, *args) if check_delegate('error')
|
122
|
+
say(:error, message, *args)
|
123
|
+
end
|
124
|
+
|
125
|
+
#---
|
126
|
+
|
127
|
+
def success(message, *args)
|
128
|
+
@logger.info("success: #{message}")
|
129
|
+
|
130
|
+
return @delegate.success(message, *args) if check_delegate('success')
|
131
|
+
say(:success, message, *args)
|
132
|
+
end
|
133
|
+
|
134
|
+
#-----------------------------------------------------------------------------
|
135
|
+
# Utilities
|
136
|
+
|
137
|
+
def format_message(type, message, options = {})
|
138
|
+
return @delegate.format_message(type, message, options) if check_delegate('format_message')
|
139
|
+
|
140
|
+
if @resource && ! @resource.empty? && options[:prefix]
|
141
|
+
prefix = "[#{@resource}]"
|
142
|
+
end
|
143
|
+
message = "#{prefix} #{message}".strip
|
144
|
+
|
145
|
+
if @color
|
146
|
+
if options.has_key?(:color)
|
147
|
+
color = COLORS[options[:color]]
|
148
|
+
message = "#{color}#{message}#{COLORS[:clear]}"
|
149
|
+
else
|
150
|
+
message = "#{COLOR_MAP[type]}#{message}#{COLORS[:clear]}" if COLOR_MAP[type]
|
151
|
+
end
|
152
|
+
end
|
153
|
+
return message
|
154
|
+
end
|
155
|
+
|
156
|
+
#---
|
157
|
+
|
158
|
+
def safe_puts(message = nil, options = {})
|
159
|
+
return @delegate.safe_puts(message, options) if check_delegate('safe_puts')
|
160
|
+
|
161
|
+
message ||= ""
|
162
|
+
options = {
|
163
|
+
:channel => @output,
|
164
|
+
:printer => @printer,
|
165
|
+
}.merge(options)
|
166
|
+
|
167
|
+
begin
|
168
|
+
options[:channel].send(options[:printer], message)
|
169
|
+
rescue Errno::EPIPE
|
170
|
+
return
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
#-----------------------------------------------------------------------------
|
175
|
+
|
176
|
+
def check_delegate(method)
|
177
|
+
return ( @delegate && @delegate.respond_to?(method.to_s) )
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|