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